@blueking/chat-x 0.0.45-beta.3 → 0.0.45-beta.5
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/components/chat-input/chat-input.vue.d.ts +5 -2
- package/dist/components/chat-message/interrupt-message/user-question/use-user-question.d.ts +1 -1
- package/dist/composables/use-global-config.d.ts +3 -0
- package/dist/index.css +1 -1
- package/dist/index.js +94 -86
- package/dist/index.js.map +1 -1
- package/dist/mcp/generated/docs/chat-container.md +53 -9
- package/dist/mcp/generated/docs/chat-input.md +33 -1
- package/dist/mcp/generated/docs/theme.md +48 -2
- package/dist/mcp/generated/docs/use-full-screen.md +3 -3
- package/dist/mcp/generated/docs/use-global-config.md +20 -5
- package/dist/mcp/generated/docs/user-question-card.md +19 -2
- package/dist/mcp/generated/index.json +4 -4
- package/package.json +1 -1
|
@@ -30,18 +30,19 @@
|
|
|
30
30
|
- **消息分组**:内置 `useMessageGroup` 自动处理消息分组、Tool 合并、Loading 注入
|
|
31
31
|
- **输入区状态推导**:传给 `MessageContainer` 与 `ChatInput` 的 `messageStatus` 为内部计算值 `inputStatus`:当分组中存在 id 为 `LOADING_MESSAGE_ID`(`'__loading__'`,由 `useMessageGroup` 注入的占位 Loading 消息)时,对内使用 `MessageStatus.Fetching`;否则使用外部传入的 `messageStatus`。用于在「已发用户消息、尚未流式」阶段与流式中一致地展示停止能力,并避免输入区重复发送
|
|
32
32
|
- **待审批发送阻塞**:当消息中存在 `AIDevToolApproval` 且状态为 `pending` / `draft` 的中断项时,`useMessageGroup` 会返回待审批提示,容器在输入区上方展示提示并通过 `ChatInput.sendDisabledTip` 禁止继续发送
|
|
33
|
-
- **用户问题中断**:当消息中存在待回答 `UserQuestion` 中断时,容器会在输入区上方挂载 `UserQuestionCard
|
|
33
|
+
- **用户问题中断**:当消息中存在待回答 `UserQuestion` 中断时,容器会在输入区上方挂载 `UserQuestionCard`;结构化作答走 `onInterruptResume`,用户在输入框直接发送时走 `onSendMessage` 并在第三参数附带 skip 用的 `payload`(`status: 'cancelled'`)与 `interrupt`,且不会自动清空输入框
|
|
34
34
|
- **执行摘要**:侧边栏展示工具调用 / FlowAgent 执行记录,支持关键词搜索和对话定位
|
|
35
35
|
- **侧栏全屏**:Tab 栏右侧提供全屏/退出全屏按钮,基于 `useFullScreen` 将侧栏区域(`.ai-full-screen-wrapper`)以浏览器原生全屏展示;全屏时 Tippy 的 `appendTo` 自动切换为全屏容器,避免 tooltip 被遮挡
|
|
36
36
|
- **自定义 Tab**:通过 `useCustomTabProvider` 支持动态添加自定义 Tab(如节点详情)
|
|
37
37
|
- **分享模式**:内置消息多选分享流程,选中用户消息后确认分享
|
|
38
38
|
- **渲染模式注入**:`renderMode` 会通过内部 Provider 下传给后代内容组件;例如 FlowAgent 节点在 `Share` 模式下隐藏耗时和「详情」入口
|
|
39
|
+
- **字号主题**:通过 `size` 控制 `small`(默认 12px)/ `normal`(14px)两档字号;根节点设置 `data-ai-size`,子组件通过 CSS 变量(`--ai-font-size` 等)响应式缩放;浮层(Tippy / Teleport)会同步 `document.body.dataset.aiSize`,卸载时自动清理
|
|
39
40
|
- **空状态欢迎页**:无消息时展示欢迎语和开场白
|
|
40
41
|
|
|
41
42
|
## 组件结构
|
|
42
43
|
|
|
43
44
|
```
|
|
44
|
-
ai-chat-container
|
|
45
|
+
ai-chat-container(:data-ai-size="size")
|
|
45
46
|
├── Loading(chatLoading 时)
|
|
46
47
|
└── ResizeLayout
|
|
47
48
|
├── aside(侧边栏)
|
|
@@ -117,6 +118,26 @@ ai-chat-container
|
|
|
117
118
|
|
|
118
119
|
**渲染效果**
|
|
119
120
|
|
|
121
|
+
## 字号主题
|
|
122
|
+
|
|
123
|
+
通过 `size` 切换两档字号主题。未传时默认为 `small`(12px 基准字号);设为 `normal` 时使用 14px 基准字号,并联动行高、间距与图标尺寸。
|
|
124
|
+
|
|
125
|
+
```vue
|
|
126
|
+
<template>
|
|
127
|
+
<ChatContainer
|
|
128
|
+
v-model="inputValue"
|
|
129
|
+
:messages="messages"
|
|
130
|
+
message-status="complete"
|
|
131
|
+
size="normal"
|
|
132
|
+
:on-send-message="handleSendMessage"
|
|
133
|
+
/>
|
|
134
|
+
</template>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**渲染效果**(左右对比 `size="small"` 与 `size="normal"`)
|
|
138
|
+
|
|
139
|
+
> CSS 变量与档位取值详见 [主题配置 — 字号主题](../../theme/theme#字号主题)。
|
|
140
|
+
|
|
120
141
|
## 侧边栏与执行摘要
|
|
121
142
|
|
|
122
143
|
侧边栏默认包含「执行情况」Tab,展示所有工具调用和 FlowAgent 类型的 Activity 消息。支持关键词搜索过滤和点击定位到对话中的消息位置。
|
|
@@ -347,7 +368,10 @@ ai-chat-container
|
|
|
347
368
|
|
|
348
369
|
## 用户问题中断
|
|
349
370
|
|
|
350
|
-
当会话中最近一条待处理 interrupt 包含 `InterruptReason.UserQuestion` 时,`ChatContainer` 会在 `ChatInput` 上方显示 [UserQuestionCard](/components/agent/user-question-card)
|
|
371
|
+
当会话中最近一条待处理 interrupt 包含 `InterruptReason.UserQuestion` 时,`ChatContainer` 会在 `ChatInput` 上方显示 [UserQuestionCard](/components/agent/user-question-card)。
|
|
372
|
+
|
|
373
|
+
- **结构化作答**:用户在卡片内完成选择或点击「跳过」后,通过 `onInterruptResume(payload, interrupt)` 回传 `UserQuestionResume`。
|
|
374
|
+
- **输入框发送**:用户也可在输入框直接点击发送;容器会调用 `onSendMessage(content, docSchema, options)`,其中 `options.interrupt` 为当前激活的 UserQuestion,`options.payload` 为 `buildSkipResumePayload` 生成的 skip resume(`status: 'cancelled'`,`answers: []`)。此时**不会自动清空**输入框,由业务侧在 `onSendMessage` 内决定如何处理 `content` 与中断恢复。
|
|
351
375
|
|
|
352
376
|
```vue
|
|
353
377
|
<template>
|
|
@@ -361,18 +385,35 @@ ai-chat-container
|
|
|
361
385
|
</template>
|
|
362
386
|
|
|
363
387
|
<script setup lang="ts">
|
|
364
|
-
import {
|
|
388
|
+
import {
|
|
389
|
+
type OnInterruptResume,
|
|
390
|
+
type UserMessage,
|
|
391
|
+
type TagSchema,
|
|
392
|
+
type Interrupt,
|
|
393
|
+
type InterruptResume,
|
|
394
|
+
} from '@blueking/chat-x';
|
|
365
395
|
|
|
366
396
|
const handleInterruptResume: OnInterruptResume = async (payload, interrupt) => {
|
|
367
|
-
//
|
|
368
|
-
// 自由文本输入也会转换为 label: 'others' 的单条回答
|
|
397
|
+
// UserQuestionCard 完成 / 跳过时 payload 为 UserQuestionResume
|
|
369
398
|
await resumeAgent({ interruptId: interrupt.id, resume: payload });
|
|
370
399
|
};
|
|
400
|
+
|
|
401
|
+
const handleSendMessage = async (
|
|
402
|
+
content: UserMessage['content'],
|
|
403
|
+
docSchema: TagSchema,
|
|
404
|
+
options?: { interrupt?: Interrupt; payload?: InterruptResume },
|
|
405
|
+
) => {
|
|
406
|
+
if (options?.interrupt && options?.payload) {
|
|
407
|
+
// 存在 UserQuestion 时发送:附带 skip resume,content 仍为输入框文本
|
|
408
|
+
await resumeAgent({ interruptId: options.interrupt.id, resume: options.payload });
|
|
409
|
+
// 业务侧自行决定是否将 content 作为新用户消息继续发送
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
await sendMessage(content, docSchema);
|
|
413
|
+
};
|
|
371
414
|
</script>
|
|
372
415
|
```
|
|
373
416
|
|
|
374
|
-
如果没有传入 `onInterruptResume`,输入框自由文本不会被中断逻辑截获,仍然走普通 `onSendMessage`,避免输入被静默清空。
|
|
375
|
-
|
|
376
417
|
## 自定义消息组渲染
|
|
377
418
|
|
|
378
419
|
通过 `#group` 插槽可替换单个消息组的默认内容,透传至内部 `MessageContainer`。外层消息组容器(`id`、hover、选中背景)仍由 `MessageContainer` 管理。
|
|
@@ -496,6 +537,7 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
|
|
|
496
537
|
| getSideTabRenderComponent | `(h, tab, { removeCustomTab }) => VNode \| undefined` | — | 自定义侧栏 Tab 标签渲染;未返回时使用默认图标 + 文案 + 关闭按钮 |
|
|
497
538
|
| openingRemark | `string` | — | 开场白,无消息时显示,支持 Markdown |
|
|
498
539
|
| placement | `'left' \| 'right'` | `'left'` | 侧边栏位置 |
|
|
540
|
+
| size | `'normal' \| 'small'` | `'small'` | 字号主题档位:`small` 为 12px 基准,`normal` 为 14px 基准;根节点设置 `data-ai-size` 并注入 `useGlobalConfig` |
|
|
499
541
|
| resizeProps | `{ disabled?: boolean; initialDivide?: number \| string; max?: number; min?: number }` | — | 透传给内部 `ResizeLayout` 的可选配置,与默认 `collapsible: false`、`immediate: true`、`min: 400` 合并;`placement` 始终取自本组件 `placement`;`initialDivide` 可为像素数字或百分比等字符串(与 bkui ResizeLayout 一致) |
|
|
500
542
|
| onCustomTabChange | `(tab: CustomTab) => Promise<any>` | — | 自定义 Tab 切换回调,返回值作为 Tab 组件 props |
|
|
501
543
|
|
|
@@ -613,4 +655,6 @@ interface Shortcut {
|
|
|
613
655
|
- [ExecutionSummary](/components/agent/execution-summary) — 执行摘要侧栏
|
|
614
656
|
- [SelectionFooter](/components/input/selection-footer) — 多选操作栏
|
|
615
657
|
- [ToolBtn](/components/feedback/tool-btn) — 侧栏全屏按钮(自定义插槽)
|
|
616
|
-
- [useFullScreen](/composables/use-full-screen) — 侧栏全屏控制
|
|
658
|
+
- [useFullScreen](/composables/use-full-screen) — 侧栏全屏控制
|
|
659
|
+
- [useGlobalConfig](/composables/use-global-config) — 注入 `size` 与 `supportUpload`
|
|
660
|
+
- [主题配置](/theme/theme) — 字号主题 CSS 变量
|
|
@@ -93,6 +93,31 @@ chat-input-container
|
|
|
93
93
|
|
|
94
94
|
> **实现细节**:组件内部用 `messageState` 计算属性决定实际按钮状态:当 `messageStatus` 为 `pending`、`streaming` 或 `fetching` 时直接使用该状态(确保停止按钮始终可用);否则当输入为空或仅含空白字符时强制为 `disabled`,其余情况使用 `messageStatus` 的值。`fetching` 时按 Enter **不会**触发发送(避免请求中与 Loading 占位阶段重复提交)。
|
|
95
95
|
|
|
96
|
+
### onSendMessage 第三参数 options(UserQuestion 上下文)
|
|
97
|
+
|
|
98
|
+
`ChatInput` 自身调用 `onSendMessage` 时只传前两个参数。当组件被 [ChatContainer](/components/setup/chat-container) 包裹且存在待回答 `UserQuestion` 中断时,容器会在用户点击发送时注入第三个参数:
|
|
99
|
+
|
|
100
|
+
| 字段 | 类型 | 说明 |
|
|
101
|
+
| ----------- | ------------------ | -------------------------------------------------------------------- |
|
|
102
|
+
| `interrupt` | `Interrupt` | 当前激活的 `UserQuestionInterrupt` |
|
|
103
|
+
| `payload` | `InterruptResume` | skip resume(`status: 'cancelled'`,`payload.answers` 为空数组) |
|
|
104
|
+
|
|
105
|
+
此场景下容器**不会**自动清空 `modelValue`,业务侧需在 `onSendMessage` 内自行处理消息发送与 `resumeAgent` 的先后顺序。结构化作答仍通过 `UserQuestionCard` → `onInterruptResume` 完成。
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const handleSendMessage = async (
|
|
109
|
+
content: UserMessage['content'],
|
|
110
|
+
docSchema: TagSchema,
|
|
111
|
+
options?: { interrupt?: Interrupt; payload?: InterruptResume },
|
|
112
|
+
) => {
|
|
113
|
+
if (options?.interrupt && options?.payload) {
|
|
114
|
+
await resumeAgent({ interruptId: options.interrupt.id, resume: options.payload });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await sendMessage(content, docSchema);
|
|
118
|
+
};
|
|
119
|
+
```
|
|
120
|
+
|
|
96
121
|
### sendDisabledTip(业务阻塞发送)
|
|
97
122
|
|
|
98
123
|
当业务侧需要临时阻止发送但仍允许用户输入时,可传入 `sendDisabledTip`。组件会置灰发送按钮,按钮 tooltip 展示该文案,并拦截点击发送、按 Enter 发送和 `triggerSendMessage()`:
|
|
@@ -504,7 +529,7 @@ chat-input-container
|
|
|
504
529
|
| sendDisabledTip | `string` | - | - | 业务阻塞发送时的 tooltip 提示;传入后发送按钮置灰,点击、Enter 与 `triggerSendMessage()` 均不会发送 |
|
|
505
530
|
| supportUpload | `boolean` | `true` | - | 是否显示文件上传按钮 |
|
|
506
531
|
| tippyOptions | `AITippyProps` | — | - | 透传给 FileUploadBtn 和 InputAttachment 的 tooltip 配置 |
|
|
507
|
-
| onSendMessage | `(content: UserMessage['content'], docSchema: TagSchema) => Promise<void>` | - | - | 发送消息回调,无文件时 content
|
|
532
|
+
| onSendMessage | `(content: UserMessage['content'], docSchema: TagSchema, options?: { interrupt?: Interrupt; payload?: InterruptResume }) => Promise<void>` | - | - | 发送消息回调,无文件时 content 为字符串,有文件时为数组;经 [ChatContainer](/components/setup/chat-container) 使用时,存在待回答 UserQuestion 会传入第三参数 `options` |
|
|
508
533
|
| onStopSending | `() => Promise<void>` | - | - | 停止发送回调,点击停止按钮时触发 |
|
|
509
534
|
| onUpload | `(file: File) => Promise<{ download_url?: string }>` | - | - | 文件上传回调(每次单文件) |
|
|
510
535
|
|
|
@@ -600,6 +625,13 @@ type SendContent =
|
|
|
600
625
|
// 有文件时:数组
|
|
601
626
|
{ type: 'binary'; url?: string; mimeType: string; filename: string } | { type: 'text'; text: string }
|
|
602
627
|
>;
|
|
628
|
+
|
|
629
|
+
// onSendMessage 完整签名(第三参数由 ChatContainer 在 UserQuestion 场景注入)
|
|
630
|
+
type OnSendMessage = (
|
|
631
|
+
content: SendContent,
|
|
632
|
+
docSchema: TagSchema,
|
|
633
|
+
options?: { interrupt?: Interrupt; payload?: InterruptResume },
|
|
634
|
+
) => Promise<void>;
|
|
603
635
|
```
|
|
604
636
|
|
|
605
637
|
## 完整集成示例
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
说明通过 SCSS 变量(尺寸、颜色、z-index
|
|
4
|
+
说明通过 SCSS 变量(尺寸、颜色、z-index)、字号主题 CSS 变量(data-ai-size 切换 small/normal)与 CSS 类覆盖自定义主题。 ChatContainer.size 控制根节点 data-ai-size;浮层同步 document.body.dataset.aiSize。含渐变边框 mixin、骨架屏类 ai-skeleton-element 等。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **chat-container** — 整体布局与侧栏
|
|
@@ -26,6 +26,51 @@
|
|
|
26
26
|
import { ChatInput, MessageContainer } from '@blueking/chat-x';
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## 字号主题
|
|
30
|
+
|
|
31
|
+
组件库通过根节点 `[data-ai-size]` 切换两档字号主题,内部组件统一引用 CSS 变量(均带兜底值,无 provider 时退回 `small`)。
|
|
32
|
+
|
|
33
|
+
### 切换方式
|
|
34
|
+
|
|
35
|
+
| 方式 | 说明 |
|
|
36
|
+
| ---- | ---- |
|
|
37
|
+
| `ChatContainer` 的 `size` prop | 推荐。根节点 `.ai-chat-container` 设置 `data-ai-size`;同时通过 `useGlobalConfig` 注入 `size` 供逻辑层读取 |
|
|
38
|
+
| 手动设置 `data-ai-size` | 在任意祖先元素上设置 `data-ai-size="small"` 或 `data-ai-size="normal"`,后代继承 CSS 变量 |
|
|
39
|
+
| `document.body.dataset.aiSize` | `ChatContainer` 会自动同步,供 Tippy / Teleport 等挂载到 `body` 的浮层继承字号变量;容器卸载时清理 |
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<template>
|
|
43
|
+
<ChatContainer v-model="input" :messages="messages" size="normal" />
|
|
44
|
+
</template>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### CSS 变量
|
|
48
|
+
|
|
49
|
+
定义于 `src/styles/size-theme.scss`,随 `global.scss` 自动引入:
|
|
50
|
+
|
|
51
|
+
| 变量名 | `small`(默认) | `normal` | 说明 |
|
|
52
|
+
| ------ | --------------- | -------- | ---- |
|
|
53
|
+
| `--ai-font-size` | `12px` | `14px` | 基准字号 |
|
|
54
|
+
| `--ai-line-height` | `20px` | `24px` | 标准行高 |
|
|
55
|
+
| `--ai-line-height-compact` | `20px` | `22px` | 紧凑行高 |
|
|
56
|
+
| `--ai-spacing-comfortable` | `8px` | `12px` | 舒适间距(如消息气泡水平内边距) |
|
|
57
|
+
| `--ai-icon-size` | `16px` | `20px` | 标准图标尺寸 |
|
|
58
|
+
| `--ai-icon-size-sm` | `16px` | `18px` | 小号图标尺寸 |
|
|
59
|
+
|
|
60
|
+
组件样式中统一使用 `var(--ai-font-size, 12px)` 等形式引用,保证无 `data-ai-size` 时仍退回 small 档位。
|
|
61
|
+
|
|
62
|
+
```scss
|
|
63
|
+
// 示例:在自定义样式中复用字号主题变量
|
|
64
|
+
.my-custom-panel {
|
|
65
|
+
font-size: var(--ai-font-size, 12px);
|
|
66
|
+
line-height: var(--ai-line-height, 20px);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 骨架屏
|
|
71
|
+
|
|
72
|
+
全局类 `.ai-skeleton-element` 用于加载占位(如 FlowAgent 节点详情、UserFeedback 原因列表)。可通过 `.skeleton-element-lg` 修饰尺寸。详见各业务组件文档中的加载态说明。
|
|
73
|
+
|
|
29
74
|
## SCSS 变量
|
|
30
75
|
|
|
31
76
|
组件库使用以下 SCSS 变量,可以在项目中覆盖:
|
|
@@ -383,6 +428,7 @@ $selection-z-index: $shortcut-menu-z-index + 1;
|
|
|
383
428
|
|
|
384
429
|
## 关联组件
|
|
385
430
|
|
|
386
|
-
- [ChatContainer](../components/setup/chat-container) —
|
|
431
|
+
- [ChatContainer](../components/setup/chat-container) — 布局与字号主题根节点(`size` prop)
|
|
432
|
+
- [useGlobalConfig](../composables/use-global-config) — 注入 `size` 供后代读取
|
|
387
433
|
- [ChatInput](../components/input/chat-input) — 输入区变量与类名
|
|
388
434
|
- [MessageContainer](../components/setup/message-container) — 消息列表区域
|
|
@@ -65,7 +65,7 @@ useFullScreen(target?)
|
|
|
65
65
|
|
|
66
66
|
`ChatContainer` 将侧栏包裹在 `.ai-full-screen-wrapper` 中,通过 `useFullScreen(fullScreenRef)` 控制侧栏全屏;Tab 栏 `#setting` 插槽内的 `ToolBtn` 使用自定义插槽渲染 `FullScreenIcon` / `UnFullScreenIcon`。
|
|
67
67
|
|
|
68
|
-
详见 [ChatContainer 侧栏全屏](../components/
|
|
68
|
+
详见 [ChatContainer 侧栏全屏](../components/setup/chat-container.md#侧栏全屏)。
|
|
69
69
|
|
|
70
70
|
## API
|
|
71
71
|
|
|
@@ -110,5 +110,5 @@ declare function useFullScreen(target?: MaybeRef<HTMLElement | null>): UseFullSc
|
|
|
110
110
|
|
|
111
111
|
## 关联组件
|
|
112
112
|
|
|
113
|
-
- [ChatContainer](../components/
|
|
114
|
-
- [ToolBtn](../components/
|
|
113
|
+
- [ChatContainer](../components/setup/chat-container.md) — 内置侧栏全屏按钮
|
|
114
|
+
- [ToolBtn](../components/feedback/tool-btn.md) — 全屏按钮自定义插槽
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
useGlobalConfig 接收 GlobalConfig(含 supportUpload: ComputedRef<boolean>),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig;
|
|
4
|
+
useGlobalConfig 接收 GlobalConfig(含 size?: ComputedRef<AiSizeMode>、supportUpload: ComputedRef<boolean>),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig 注入 size 与 supportUpload; 后代组件可通过 injectGlobalConfig 读取配置;字号主题主要通过根节点 data-ai-size 与 CSS 变量生效。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **chat-container** — 根容器调用 useGlobalConfig 注入 supportUpload
|
|
@@ -13,14 +13,20 @@ useGlobalConfig 接收 GlobalConfig(含 supportUpload: ComputedRef<boolean>)
|
|
|
13
13
|
|
|
14
14
|
> **分类**:composable
|
|
15
15
|
|
|
16
|
-
在聊天容器根组件与子组件之间通过 Vue `provide` / `inject`
|
|
16
|
+
在聊天容器根组件与子组件之间通过 Vue `provide` / `inject` 共享**全局展示相关配置**(当前包括字号主题档位 `size`、是否支持上传 `supportUpload`)。与 Teleport 插槽 ID 无关。
|
|
17
|
+
|
|
18
|
+
> 字号主题主要通过 `ChatContainer` 根节点的 `data-ai-size` 与 CSS 变量(`--ai-font-size` 等)生效;`GlobalConfig.size` 供后代在逻辑层读取当前档位,样式层无需逐组件传参。
|
|
17
19
|
|
|
18
20
|
## 工作原理
|
|
19
21
|
|
|
20
22
|
```
|
|
21
23
|
ChatContainer(根)
|
|
22
|
-
├──
|
|
23
|
-
|
|
24
|
+
├── :data-ai-size="size"(CSS 变量作用域)
|
|
25
|
+
├── useGlobalConfig({
|
|
26
|
+
│ size: computed(() => props.size ?? 'small'),
|
|
27
|
+
│ supportUpload: computed(() => props.supportUpload ?? false),
|
|
28
|
+
│ })
|
|
29
|
+
│ └── provide(GLOBAL_CONFIG_TOKEN, { size, supportUpload })
|
|
24
30
|
│
|
|
25
31
|
└── MessageContainer → … → UserMessage 等
|
|
26
32
|
|
|
@@ -43,10 +49,12 @@ UserMessage(后代)
|
|
|
43
49
|
import { useGlobalConfig } from '@blueking/chat-x';
|
|
44
50
|
|
|
45
51
|
const props = defineProps<{
|
|
52
|
+
size?: 'normal' | 'small';
|
|
46
53
|
supportUpload?: boolean;
|
|
47
54
|
}>();
|
|
48
55
|
|
|
49
56
|
useGlobalConfig({
|
|
57
|
+
size: computed(() => props.size ?? 'small'),
|
|
50
58
|
supportUpload: computed(() => props.supportUpload ?? false),
|
|
51
59
|
});
|
|
52
60
|
</script>
|
|
@@ -75,11 +83,15 @@ import type { ComputedRef } from 'vue';
|
|
|
75
83
|
|
|
76
84
|
export const GLOBAL_CONFIG_TOKEN: unique symbol;
|
|
77
85
|
|
|
86
|
+
export type AiSizeMode = 'normal' | 'small';
|
|
87
|
+
|
|
78
88
|
export type GlobalConfig = {
|
|
89
|
+
size?: ComputedRef<AiSizeMode>;
|
|
79
90
|
supportUpload: ComputedRef<boolean>;
|
|
80
91
|
};
|
|
81
92
|
|
|
82
93
|
export function useGlobalConfig(options: GlobalConfig): {
|
|
94
|
+
size?: ComputedRef<AiSizeMode>;
|
|
83
95
|
supportUpload: ComputedRef<boolean>;
|
|
84
96
|
};
|
|
85
97
|
|
|
@@ -96,12 +108,14 @@ export function injectGlobalConfig(): GlobalConfig | undefined;
|
|
|
96
108
|
|
|
97
109
|
| 字段 | 说明 |
|
|
98
110
|
| --------------- | ------------------------------------------------------------------------ |
|
|
111
|
+
| `size` | 可选。字号主题档位 `normal`(14px)/ `small`(12px),与 `ChatContainer.size` 对齐 |
|
|
99
112
|
| `supportUpload` | 是否支持上传,与根容器 `ChatContainer` 的 `supportUpload` 等展示策略对齐 |
|
|
100
113
|
|
|
101
114
|
### `useGlobalConfig(options)`
|
|
102
115
|
|
|
103
116
|
| 参数 | 说明 |
|
|
104
117
|
| ----------------------- | ------------------------------------------------------------------------------------- |
|
|
118
|
+
| `options.size` | 可选。字号主题档位,建议使用 `computed(() => props.size ?? 'small')` 与根 props 同步 |
|
|
105
119
|
| `options.supportUpload` | 是否支持上传,建议使用 `computed(() => props.supportUpload ?? false)` 与根 props 同步 |
|
|
106
120
|
|
|
107
121
|
- 调用后立即 `provide(GLOBAL_CONFIG_TOKEN, options)`。
|
|
@@ -122,4 +136,5 @@ export function injectGlobalConfig(): GlobalConfig | undefined;
|
|
|
122
136
|
|
|
123
137
|
## 关联组件
|
|
124
138
|
|
|
125
|
-
- [ChatContainer](../components/setup/chat-container) — 调用 `useGlobalConfig` 注入 `supportUpload`
|
|
139
|
+
- [ChatContainer](../components/setup/chat-container) — 调用 `useGlobalConfig` 注入 `size` 与 `supportUpload`
|
|
140
|
+
- [主题配置](../theme/theme) — `data-ai-size` 与 CSS 变量说明
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- **自定义作答形态**:通过 `#question` slot 可替换默认选择题,渲染任意表单;作答有效时调用 `setAnswer` 回传 `UserQuestionAnswerItem`,无效时传 `undefined`。
|
|
30
30
|
- **完成校验**:所有题目均已作答(`setAnswer` 收到有效答案)后才允许点击「完成」。
|
|
31
31
|
- **跳过**:点击「跳过」返回 `status: 'cancelled'` 与空 `answers`。
|
|
32
|
-
-
|
|
32
|
+
- **输入框发送**:存在待回答 UserQuestion 时,用户也可在 `ChatInput` 直接发送;`ChatContainer` 会调用 `onSendMessage` 并在第三参数附带与「跳过」等价的 skip `payload` 及 `interrupt`,输入框内容不会自动清空。
|
|
33
33
|
|
|
34
34
|
## 数据协议
|
|
35
35
|
|
|
@@ -141,7 +141,24 @@ const payload = {
|
|
|
141
141
|
/>
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
- 卡片内「完成 / 跳过」→ `onInterruptResume(payload, interrupt)`
|
|
145
|
+
- 输入框直接发送 → `onSendMessage(content, docSchema, { interrupt, payload })`,其中 `payload` 由 `buildSkipResumePayload(interrupt)` 生成(`status: 'cancelled'`)
|
|
146
|
+
|
|
147
|
+
## 工具函数 buildSkipResumePayload
|
|
148
|
+
|
|
149
|
+
从 `@blueking/chat-x` 导出,用于构造 UserQuestion 的 skip resume(与卡片「跳过」及输入框发送时容器注入的 `options.payload` 一致):
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { buildSkipResumePayload, InterruptReason } from '@blueking/chat-x';
|
|
153
|
+
|
|
154
|
+
const payload = buildSkipResumePayload(interrupt);
|
|
155
|
+
// {
|
|
156
|
+
// interruptId: interrupt.id,
|
|
157
|
+
// reason: InterruptReason.UserQuestion,
|
|
158
|
+
// status: 'cancelled',
|
|
159
|
+
// payload: { answers: [] },
|
|
160
|
+
// }
|
|
161
|
+
```
|
|
145
162
|
|
|
146
163
|
## 自定义题目渲染(#question slot)
|
|
147
164
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "2.0.0",
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-10T07:05:58.442Z",
|
|
4
4
|
"domains": {
|
|
5
5
|
"setup": {
|
|
6
6
|
"label": "对话搭建",
|
|
@@ -1575,8 +1575,8 @@
|
|
|
1575
1575
|
"name": "useGlobalConfig",
|
|
1576
1576
|
"slug": "use-global-config",
|
|
1577
1577
|
"kind": "composable",
|
|
1578
|
-
"description": "在聊天根容器与子组件之间通过 provide/inject
|
|
1579
|
-
"aiSummary": "useGlobalConfig 接收 GlobalConfig(含 supportUpload: ComputedRef<boolean>),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig;
|
|
1578
|
+
"description": "在聊天根容器与子组件之间通过 provide/inject 共享全局展示配置(字号主题档位、是否支持上传等)。",
|
|
1579
|
+
"aiSummary": "useGlobalConfig 接收 GlobalConfig(含 size?: ComputedRef<AiSizeMode>、supportUpload: ComputedRef<boolean>),以 GLOBAL_CONFIG_TOKEN provide 给后代; injectGlobalConfig 在子组件中取出配置,无 Provider 时返回 undefined。ChatContainer 在 setup 中调用 useGlobalConfig 注入 size 与 supportUpload; 后代组件可通过 injectGlobalConfig 读取配置;字号主题主要通过根节点 data-ai-size 与 CSS 变量生效。",
|
|
1580
1580
|
"relatedComponents": [
|
|
1581
1581
|
{
|
|
1582
1582
|
"slug": "chat-container",
|
|
@@ -1833,7 +1833,7 @@
|
|
|
1833
1833
|
"slug": "theme",
|
|
1834
1834
|
"kind": "theme",
|
|
1835
1835
|
"description": "`@blueking/chat-x` 使用 SCSS 变量和 CSS 类来控制样式,支持通过覆盖变量或样式来自定义主题。",
|
|
1836
|
-
"aiSummary": "说明通过 SCSS 变量(尺寸、颜色、z-index
|
|
1836
|
+
"aiSummary": "说明通过 SCSS 变量(尺寸、颜色、z-index)、字号主题 CSS 变量(data-ai-size 切换 small/normal)与 CSS 类覆盖自定义主题。 ChatContainer.size 控制根节点 data-ai-size;浮层同步 document.body.dataset.aiSize。含渐变边框 mixin、骨架屏类 ai-skeleton-element 等。",
|
|
1837
1837
|
"relatedComponents": [
|
|
1838
1838
|
{
|
|
1839
1839
|
"slug": "chat-container",
|