@blueking/chat-x 0.0.45-beta.2 → 0.0.45-beta.4

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 (54) hide show
  1. package/dist/ag-ui/types/contents.d.ts +5 -0
  2. package/dist/ag-ui/types/interrupt.d.ts +35 -5
  3. package/dist/components/ai-buttons/tool-btn/tool-btn.vue.d.ts +11 -1
  4. package/dist/components/chat-content/flow-agent-content/flow-agent-content.vue.d.ts +4 -0
  5. package/dist/components/chat-content/flow-agent-content/flow-agent-node-detail.vue.d.ts +2 -0
  6. package/dist/components/chat-content/flow-agent-content/flow-agent-state.d.ts +34 -0
  7. package/dist/components/chat-content/flow-agent-content/use-flow-agent.d.ts +51 -0
  8. package/dist/components/chat-content/flow-agent-content/use-flow-node-actions.d.ts +32 -0
  9. package/dist/components/chat-content/flow-agent-content/use-flow-tab.d.ts +18 -0
  10. package/dist/components/chat-input/ai-slash-input/ai-skill-list/ai-skill-list.vue.d.ts +8 -0
  11. package/dist/components/chat-input/ai-slash-input/ai-slash-input.vue.d.ts +3 -1
  12. package/dist/components/chat-input/chat-input.vue.d.ts +3 -1
  13. package/dist/components/chat-message/activity-message/activity-message.vue.d.ts +4 -1
  14. package/dist/components/index.d.ts +4 -1
  15. package/dist/composables/index.d.ts +1 -0
  16. package/dist/composables/use-common.d.ts +1 -1
  17. package/dist/composables/use-custom-tab.d.ts +1 -1
  18. package/dist/composables/use-full-screen.d.ts +17 -0
  19. package/dist/composables/use-global-config.d.ts +3 -0
  20. package/dist/composables/use-message-group.d.ts +9 -0
  21. package/dist/icons/execution.d.ts +3 -0
  22. package/dist/icons/index.d.ts +1 -0
  23. package/dist/icons/screen.d.ts +6 -0
  24. package/dist/index.css +1 -1
  25. package/dist/index.js +4400 -4153
  26. package/dist/index.js.map +1 -1
  27. package/dist/lang/lang.d.ts +5 -1
  28. package/dist/mcp/generated/docs/activity-message.md +33 -9
  29. package/dist/mcp/generated/docs/chat-container.md +103 -20
  30. package/dist/mcp/generated/docs/file-upload-btn.md +1 -1
  31. package/dist/mcp/generated/docs/flow-agent-content.md +47 -7
  32. package/dist/mcp/generated/docs/interrupt-message.md +2 -2
  33. package/dist/mcp/generated/docs/interrupt.md +80 -8
  34. package/dist/mcp/generated/docs/markdown-content.md +23 -0
  35. package/dist/mcp/generated/docs/message-container.md +1 -1
  36. package/dist/mcp/generated/docs/message-render.md +3 -3
  37. package/dist/mcp/generated/docs/message-tools.md +3 -3
  38. package/dist/mcp/generated/docs/shortcut-render.md +5 -1
  39. package/dist/mcp/generated/docs/theme.md +48 -2
  40. package/dist/mcp/generated/docs/tool-approval-card.md +2 -2
  41. package/dist/mcp/generated/docs/tool-btn.md +37 -6
  42. package/dist/mcp/generated/docs/use-flow-node-actions.md +124 -0
  43. package/dist/mcp/generated/docs/use-full-screen.md +114 -0
  44. package/dist/mcp/generated/docs/use-global-config.md +20 -5
  45. package/dist/mcp/generated/index.json +36 -4
  46. package/dist/plugins/index.d.ts +1 -0
  47. package/dist/plugins/markdown-bk-inline-style.d.ts +20 -0
  48. package/dist/types/custom.d.ts +1 -0
  49. package/dist/types/editor.d.ts +6 -0
  50. package/dist/types/input.d.ts +1 -1
  51. package/dist/types/tool.d.ts +3 -3
  52. package/dist/utils/index.d.ts +1 -0
  53. package/dist/utils/utils.d.ts +1 -0
  54. package/package.json +1 -1
@@ -182,6 +182,7 @@ props.content → completeMarkdownSyntax → md.parse → groupTokens → groupe
182
182
 
183
183
  | 插件 | 语法 | 功能 |
184
184
  | --------------------------- | ------------------- | -------------------- |
185
+ | `markdownItBkInlineStyle` | 见下文「蓝鲸行内样式」 | 安全行内颜色/字号/粗斜体(非 HTML) |
185
186
  | `markdown-it-footnote` | `[^1]` | 脚注 |
186
187
  | `markdown-it-ins` | `++text++` | 下划线 |
187
188
  | `markdown-it-mark` | `==text==` | 高亮 |
@@ -192,8 +193,30 @@ props.content → completeMarkdownSyntax → md.parse → groupTokens → groupe
192
193
  | `markdownItLatex` | `$...$` / `$$...$$` | KaTeX 数学公式 token |
193
194
  | `markdownItContainer` | `::: hljs-left` 等 | 自定义对齐容器(class 与 highlight.js 命名对齐) |
194
195
 
196
+ ### 蓝鲸行内样式(`markdownItBkInlineStyle`)
197
+
198
+ 不开启 `html: true`,由专用语法生成带白名单 `style` 的 `<span class="bk-md-inline-style">`。
199
+
200
+ **语法**:`::bk{` *属性* `}` *正文* `:/bk::`
201
+
202
+ - 属性写在 `{}` 内,使用 `;` 分隔;每项为 `键=值` 或 `键:值`。
203
+ - 正文支持行内 Markdown(如 `**粗体**`)。
204
+ - 结束标记必须为字面量 `:/bk::`,请勿在正文中出现该序列。
205
+
206
+ **支持的键**:`color` / `c`、`background-color`、`font-size`、`bold`、`italic`(详见 `plugins/markdown-bk-inline-style.ts` 内注释)。
207
+
208
+ **示例**:
209
+
210
+ ```markdown
211
+ ::bk{color:#c00;font-size:18px}**重要**:/bk::
212
+ ::bk{background-color:yellow}高亮:/bk::
213
+ ::bk{bold;italic}强调:/bk::
214
+ ```
215
+
195
216
  ### 安全性
196
217
 
218
+ `MarkdownIt` **不**开启 `html: true`,用户无法插入任意 HTML 标签;行内彩色/字号等请使用上文「蓝鲸行内样式」扩展。
219
+
197
220
  `VNodeRenderer` 渲染的 HTML 统一经过 DOMPurify 过滤,并额外允许 KaTeX 所需标签:
198
221
 
199
222
  ```typescript
@@ -502,7 +502,7 @@ AI 回复状态为 `error` 时,消息以错误样式展示:
502
502
  | messageGroups | `MessageGroup[]` | — | 预计算的消息分组;传入时跳过内部分组逻辑,由 `ChatContainer` 通过 `useMessageGroup` 提供 |
503
503
  | messageStatus | `MessageStatus` | — | 当前整体消息状态,控制底部「停止生成」按钮显示;`ChatContainer` 会结合末尾 Loading 占位推导 `fetching` 等再传入 |
504
504
  | messageToolsStatus | `MessageToolsStatus` | — | 工具栏状态,透传给 `MessageTools` 和 `MessageRender` |
505
- | messageToolsTippyOptions | `AITippyProps` | — | 透传给 `MessageTools` 和 `MessageRender`(进而透传给 `UserMessage` 的工具栏)的 Tippy 配置,用于自定义 tooltip 挂载点(如 `appendTo`)等 |
505
+ | messageToolsTippyOptions | `AITippyProps` | — | 透传给 `MessageTools` 和 `MessageRender`(进而透传给 `UserMessage` 的工具栏)的 Tippy 配置,用于自定义 tooltip 挂载点、位置等(如 `appendTo`、`placement`、`zIndex`) |
506
506
  | enableSelection | `boolean` | `false` | 是否启用多选模式 |
507
507
  | onAgentAction | `(tool: IToolBtn, messages: Message[]) => Promise<string[] \| void>` | — | AI 消息工具操作回调;`copy` 操作由内部处理,`like/unlike` 应返回反馈原因字符串数组 |
508
508
  | onAgentFeedback | `(tool: IToolBtn, messages: Message[], reasonList: string[], otherReason: string) => void` | — | AI 消息反馈提交回调(点赞/踩选完原因后触发) |
@@ -39,7 +39,7 @@ MessageRender
39
39
  │ ├── 'info' → InfoMessage(转发 message)
40
40
  │ ├── 'reasoning' → ReasoningMessage(转发 message)
41
41
  │ ├── 'tool' → ToolMessage(转发 message)
42
- │ ├── 'activity' → ActivityMessage(转发 message)
42
+ │ ├── 'activity' → ActivityMessage(转发 message + onInterruptResume
43
43
  │ ├── 'loading' → LoadingMessage(转发 message)
44
44
  │ ├── 'interrupt' → InterruptMessageRender(转发 message + onInterruptResume)
45
45
  │ │
@@ -274,7 +274,7 @@ slot 参数类型与 `AssistantMessage` 的 slot 保持一致(`Partial<Assista
274
274
  | messageToolsStatus | `MessageToolsStatus` | — | 工具按钮状态;**仅转发给 `UserMessage`** |
275
275
  | onAction | `(tool: IToolBtn) => Promise<string[] \| void>` | — | 工具操作回调;**仅转发给 `UserMessage`** |
276
276
  | onInputConfirm | `(content: UserMessage['content'], docSchema: TagSchema) => Promise<void>` | — | 用户编辑确认回调;**仅转发给 `UserMessage`** |
277
- | onInterruptResume | `(payload: InterruptResume, interrupt: Interrupt) => Promise<void>` | — | 中断响应回调;**仅转发给 `InterruptMessageRender`** |
277
+ | onInterruptResume | `(payload: InterruptResume, interrupt?: Interrupt) => Promise<void>` | — | 中断 / FlowAgent 节点操作回调;转发给 `InterruptMessageRender` 与 `ActivityMessage`(后者仅 `flow_agent` 子组件消费) |
278
278
  | onShortcutConfirm | `(formModel: Record<string, unknown>) => Promise<void>` | — | 用户快捷指令提交回调;**仅转发给 `UserMessage`** |
279
279
  | tippyOptions | `Partial<Omit<TippyOptions, 'getReferenceClientRect' \| 'triggerTarget'>>` | — | 自定义 Tippy 配置;**仅转发给 `UserMessage`** |
280
280
 
@@ -295,7 +295,7 @@ slot 参数类型与 `AssistantMessage` 的 slot 保持一致(`Partial<Assista
295
295
  | `info` | `InfoMessage` | `message` | 系统信息 / 会话分隔符 |
296
296
  | `reasoning` | `ReasoningMessage` | `message` | AI 思考过程(可折叠) |
297
297
  | `tool` | `ToolMessage` | `message` | 工具调用返回结果 |
298
- | `activity` | `ActivityMessage` | `message` | 知识检索 / 引用文档 |
298
+ | `activity` | `ActivityMessage` | `message` + `onInterruptResume` | 知识检索 / 引用文档 / FlowAgent 执行(节点重试 / 跳过) |
299
299
  | `loading` | `LoadingMessage` | `message`(字段被忽略,组件无 Props) | 等待响应的加载占位 |
300
300
  | `interrupt` | `InterruptMessageRender` | `message` + `onInterruptResume` | human-in-the-loop 中断 |
301
301
  | 其他 / 未知 | — | — | 返回 `null`,不渲染 |
@@ -363,9 +363,9 @@ const CONST_UPDATE_TOOLS = [
363
363
  import { MessageToolsStatus, type IToolBtn } from '@blueking/chat-x';
364
364
 
365
365
  interface IToolBtn {
366
- id: string; // 工具唯一标识;与 ToolIconsMap 匹配时显示内置图标,否则显示 name 文本
367
- name: string; // 工具名称,无对应图标时显示;也用作 tooltip fallback
368
- description: string; // tooltip 文本
366
+ id?: keyof typeof ToolIconsMap; // 工具唯一标识;与 ToolIconsMap 匹配时显示内置图标,否则显示 name 文本
367
+ name?: string; // 工具名称,无对应图标时显示;也用作 tooltip fallback
368
+ description?: string; // tooltip 文本
369
369
  }
370
370
 
371
371
  enum MessageToolsStatus {
@@ -349,7 +349,7 @@ const components: ShortcutComponent[] = [
349
349
  | ------------- | ------------------------------------ | ---- | ------------------------------------------------------------------------------------------ |
350
350
  | type | 见[表单类型](#表单组件类型) | ✓ | 控件类型;未知类型返回 `null`,不渲染 |
351
351
  | key | `string` | ✓ | 表单字段名;`submit` 事件返回对象以此为 key;同时作为校验 property |
352
- | name | `string` | — | 表单项标签(`Form.FormItem` `label`) |
352
+ | name | `string` | — | 表单项标签;优先于 `formItemProps.label`,通过 `#label` 插槽渲染为 `.shortcut-render-form-label` |
353
353
  | default | `string` | — | 字段初始值;优先于 `formModel`,在 `watchEffect` 中覆盖写入 |
354
354
  | fillBack | `boolean` | — | `true` 时映射为 `required: true`(必填校验),同时标记回填语义 |
355
355
  | placeholder | `string` | — | 占位文本(`input` / `textarea` / `number` 可用) |
@@ -416,6 +416,10 @@ interface BaseShortcutComponent {
416
416
  }
417
417
  ```
418
418
 
419
+ ## 样式说明
420
+
421
+ 表单项与控件会附加类型化 class,便于样式覆盖:`shortcut-render-form-item_{type}`(如 `_radio`、`_checkbox`),单选/多选项子项为 `shortcut-render-form-item_radio` / `shortcut-render-form-item_checkbox`。表单项标签使用 BEM 风格类名 `shortcut-render-form-label`。
422
+
419
423
  ## 关联组件
420
424
 
421
425
  - [ShortcutBtn](/components/input/shortcut-btn) — 与 Shortcut 数据模型一致的入口按钮
@@ -1,7 +1,7 @@
1
1
  <!-- AI SUMMARY -->
2
2
  ## 快速了解
3
3
 
4
- 说明通过 SCSS 变量(尺寸、颜色、z-index)与 CSS 类覆盖(chat-input、用户/助手消息、shortcut-btns、ai-markdown-body、tool-btn 等)自定义主题。 含渐变边框 mixin、ai-markdown-fade-in 与弹窗过渡。暗色示例通过根 class 切换。组件随包引入样式,业务侧按需覆写。
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) — 消息列表区域
@@ -129,11 +129,11 @@ ToolApprovalCard
129
129
  | 属性名 | 类型 | 默认值 | 说明 |
130
130
  | ----------------- | ---------------------------- | ------ | -------------------------------------------- |
131
131
  | interrupt | `AIDevToolApprovalInterrupt` | — | **必填**,含 `metadata.ticket` |
132
- | onInterruptResume | `OnInterruptResume` | — | 取消审批时触发,签名为 `(payload, interrupt)`,payload 为 `{ action: 'cancel' }` |
132
+ | onInterruptResume | `OnInterruptResume` | — | 取消审批时触发,签名为 `(payload, interrupt)`,payload 为 `{ operation: InterruptResumeOperation.ApprovalCancel, payload: { interrupt_id } }` |
133
133
 
134
134
  ### Events / Slots / Expose
135
135
 
136
- 无。打开链接、复制剪贴板在组件内部完成;取消审批通过 `onInterruptResume({ action: 'cancel' }, interrupt)` 通知业务侧处理。
136
+ 无。打开链接、复制剪贴板在组件内部完成;取消审批通过 `onInterruptResume({ operation: InterruptResumeOperation.ApprovalCancel, payload: { interrupt_id: interrupt.id } }, interrupt)` 通知业务侧处理。
137
137
 
138
138
  ## 依赖
139
139
 
@@ -30,8 +30,9 @@ div.ai-tool-btn(v-tippy,flex,min-width: 20px,height: 20px,border-radiu
30
30
  disabled=true → .is-disabled(color: #979ba5; cursor: not-allowed)
31
31
  :not(.is-disabled):hover → color: #4d4f56; background: #eaebf0
32
32
 
33
- ├── [id in ToolIconsMap] → <component :is="ToolIconsMap[id]" />(SVG 图标,font-size: 16px 控制大小)
34
- └── [id not in ToolIconsMap] → <div>{{ name }}</div>(文本回退,XSS 安全)
33
+ └── <slot>(默认内容,可完全自定义)
34
+ ├── [id && id in ToolIconsMap] → <component :is="ToolIconsMap[id]" />(SVG 图标)
35
+ └── [其他] → <div>{{ name }}</div>(文本回退,XSS 安全)
35
36
 
36
37
  Tippy:content=description, theme='ai-chat-box', disabled=true 时 onShow 返回 false 不显示
37
38
  click 事件:disabled=true 时被 JS 拦截,不触发 emit
@@ -56,7 +57,7 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
56
57
  | `activeLike` | 点赞(实心) | 激活态填充图标 |
57
58
  | `activeUnLike` | 不满意(实心) | 激活态填充图标 |
58
59
 
59
- > `id` 不在上表时,组件渲染 `<div>{{ name }}</div>` 作为文本回退。此时 `id` 的 TypeScript 类型会报错(`keyof typeof ToolIconsMap`),建议优先使用预置 ID。
60
+ > 未传入 `id`、或 `id` 不在上表时,组件渲染 `<div>{{ name }}</div>` 作为文本回退。也可通过默认插槽完全自定义按钮内容(如全屏图标),此时可不传 `id`。
60
61
 
61
62
  ## 基础用法
62
63
 
@@ -192,7 +193,31 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
192
193
 
193
194
  ## 未知 ID 的文本回退
194
195
 
195
- `id` 不在 `ToolIconsMap` 时渲染 `name` 文本,适用于自定义扩展场景(注意 TypeScript 会报类型错误):
196
+ `id` 不在 `ToolIconsMap` 时渲染 `name` 文本,适用于自定义扩展场景:
197
+
198
+ ## 自定义插槽内容
199
+
200
+ 通过默认插槽可完全替换内置图标/文本,适用于预置 `ToolIconsMap` 未覆盖的图标场景(如侧栏全屏按钮):
201
+
202
+ ```vue
203
+ <template>
204
+ <ToolBtn
205
+ description="全屏"
206
+ :tippy-options="{ content: '全屏' }"
207
+ @click="handleFullScreen"
208
+ >
209
+ <FullScreenIcon />
210
+ </ToolBtn>
211
+ </template>
212
+
213
+ <script setup lang="ts">
214
+ import { ToolBtn, FullScreenIcon } from '@blueking/chat-x';
215
+
216
+ const handleFullScreen = () => {
217
+ // 进入全屏逻辑
218
+ };
219
+ </script>
220
+ ```
196
221
 
197
222
  ## API
198
223
 
@@ -200,7 +225,7 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
200
225
 
201
226
  | 属性名 | 类型 | 必填 | 默认值 | 说明 |
202
227
  | ------------ | -------------------------------------------------------------------------- | ---- | ------ | ------------------------------------------------------------------------------------------------------------------ |
203
- | id | `keyof typeof ToolIconsMap` | | — | 按钮标识;在 `ToolIconsMap` 中时渲染对应 SVG 图标,否则渲染 `name` 文本 |
228
+ | id | `keyof typeof ToolIconsMap` | | — | 按钮标识;在 `ToolIconsMap` 中时渲染对应 SVG 图标,否则渲染 `name` 文本;使用插槽自定义内容时可省略 |
204
229
  | name | `string` | 否 | — | 按钮名称;`id` 无对应图标时作为文本内容渲染 |
205
230
  | description | `string` | 否 | — | Tippy tooltip 内容;`disabled=true` 时不显示 tooltip |
206
231
  | active | `boolean` | 否 | — | 激活态;`true` 时追加 `.is-active`(字色由 `id` 决定:`like`/`activeLike` 为蓝色 `#3a84ff`,其他为红色 `#E71818`) |
@@ -213,12 +238,18 @@ click 事件:disabled=true 时被 JS 拦截,不触发 emit
213
238
  | ------ | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
214
239
  | click | `(data: IToolBtn & { active?: boolean; disabled?: boolean }, event: MouseEvent)` | 点击时触发;`data` 为组件当前全量 props(含 `active`/`disabled`);`disabled=true` 时不触发 |
215
240
 
241
+ ### Slots
242
+
243
+ | 插槽名 | 说明 |
244
+ | ------- | ------------------------------------------------------------------------------------------ |
245
+ | default | 按钮内容;传入时替换默认的图标/文本渲染逻辑,常用于自定义 SVG 图标(如全屏、退出全屏按钮) |
246
+
216
247
  ## 类型定义
217
248
 
218
249
  ```typescript
219
250
  // 来自 @blueking/chat-x 导出
220
251
  interface IToolBtn {
221
- id: keyof typeof ToolIconsMap; // 限定为预置 ID
252
+ id?: keyof typeof ToolIconsMap; // 预置 ID;省略时走 name 文本或插槽
222
253
  name?: string;
223
254
  description?: string;
224
255
  }
@@ -0,0 +1,124 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ useFlowNodeActions 接收 onInterruptResume 与 openNodeDetail,返回 getNodeActions(task, node)。 失败节点按 retryable/skippable 展示重试/跳过,详情恒在末尾;点击 resume 时不传 interrupt。
5
+
6
+ ### 关联组件
7
+ - **flow-agent-content** — FlowAgentContent 内部消费,驱动节点行尾按钮组渲染
8
+
9
+ ---
10
+ <!-- FULL DOC -->
11
+
12
+ # useFlowNodeActions 节点行尾操作
13
+
14
+ > **分类**:composable
15
+
16
+ 将 FlowAgent 节点行尾的「详情(打开侧栏)」与「重试 / 跳过(回传 Agent resume)」聚合为统一的声明式操作列表。`FlowAgentContent` 只需遍历 `getNodeActions` 返回值渲染按钮,显隐与点击行为均收敛于此 composable。
17
+
18
+ 源码:`src/components/chat-content/flow-agent-content/use-flow-node-actions.ts`
19
+
20
+ ## 函数签名
21
+
22
+ ```typescript
23
+ function useFlowNodeActions(options: {
24
+ /** resume 回调(与第三方审批取消同一回调,按 payload.operation 分流) */
25
+ onInterruptResume: Ref<OnInterruptResume | undefined>;
26
+ /** 打开节点详情侧栏(复用 useFlowTab 的能力) */
27
+ openNodeDetail: (task: BkFlowTask, node: BkFlowNode) => void;
28
+ }): {
29
+ getNodeActions: (task: FlowTaskVM, node: FlowNodeVM) => FlowNodeActionVM[];
30
+ };
31
+ ```
32
+
33
+ ## 返回值:FlowNodeActionVM
34
+
35
+ ```typescript
36
+ type FlowNodeActionId =
37
+ | 'detail'
38
+ | InterruptResumeOperation.FlowNodeRetry
39
+ | InterruptResumeOperation.FlowNodeSkip;
40
+
41
+ interface FlowNodeActionVM {
42
+ icon: Component;
43
+ id: FlowNodeActionId;
44
+ label: string;
45
+ run: () => void;
46
+ }
47
+ ```
48
+
49
+ | 字段 | 说明 |
50
+ | ------- | ------------------------------ |
51
+ | `icon` | 按钮图标组件 |
52
+ | `id` | 唯一标识,用于 `v-for` key |
53
+ | `label` | 国际化文案 |
54
+ | `run` | 点击执行(详情或 resume) |
55
+
56
+ ## 操作显隐规则
57
+
58
+ | 操作 | `id` | 显隐条件 | 点击行为 |
59
+ | ---- | ------------------ | ------------------------------------------ | --------------------------------------------- |
60
+ | 重试 | `flow_node_retry` | `convergedState === 'failed'` 且 `retryable` | 调用 `onInterruptResume`,**不传** `interrupt` |
61
+ | 跳过 | `flow_node_skip` | `convergedState === 'failed'` 且 `skippable` | 同上 |
62
+ | 详情 | `detail` | 始终(Share 模式由上层组件隐藏整组) | 调用 `openNodeDetail(task.raw, node.raw)` |
63
+
64
+ 展示顺序:重试 → 跳过 → 详情。
65
+
66
+ ## resume 负载格式
67
+
68
+ ```typescript
69
+ // 重试
70
+ onInterruptResume?.({
71
+ operation: InterruptResumeOperation.FlowNodeRetry,
72
+ payload: { node_id: node.id, task_id: task.task_id },
73
+ });
74
+
75
+ // 跳过
76
+ onInterruptResume?.({
77
+ operation: InterruptResumeOperation.FlowNodeSkip,
78
+ payload: { node_id: node.id, task_id: task.task_id },
79
+ });
80
+ ```
81
+
82
+ ## 使用示例
83
+
84
+ `FlowAgentContent` 内部用法(业务侧通常通过 `MessageRender` 传入 `onInterruptResume`,无需直接调用本 composable):
85
+
86
+ ```typescript
87
+ import { toRef } from 'vue';
88
+ import { useFlowNodeActions } from '@blueking/chat-x';
89
+ // 或相对路径:'./use-flow-node-actions'
90
+
91
+ const { getNodeActions } = useFlowNodeActions({
92
+ onInterruptResume: toRef(props, 'onInterruptResume'),
93
+ openNodeDetail,
94
+ });
95
+
96
+ // 模板中
97
+ // v-for="action in getNodeActions(task, node)" :key="action.id"
98
+ // @click.stop="action.run()"
99
+ ```
100
+
101
+ ## 扩展新操作
102
+
103
+ 在 `RESUME_ACTION_DEFS` 注册表中追加一项即可,需声明 `visible` 与 `operation` 枚举:
104
+
105
+ ```typescript
106
+ const RESUME_ACTION_DEFS: FlowNodeResumeActionDef[] = [
107
+ // 现有:重试、跳过
108
+ {
109
+ icon: MyIcon,
110
+ id: InterruptResumeOperation.MyNewOp, // 需先在 InterruptResumeOperation 扩展
111
+ label: () => t('新操作'),
112
+ visible: node => /* 自定义显隐 */,
113
+ },
114
+ ];
115
+ ```
116
+
117
+ 同时在 `interrupt.ts` 扩展 `InterruptResumeOperation` 与 `FlowNodeResume` 联合类型。
118
+
119
+ ## 关联文档
120
+
121
+ - [FlowAgentContent 执行内容](/components/agent/flow-agent-content) — 消费方组件
122
+ - [中断类型 Interrupt](/types/interrupt) — `InterruptResumeOperation`、`FlowNodeResume`、`OnInterruptResume`
123
+ - [ActivityMessage 活动消息](/components/message/activity-message) — `onInterruptResume` 透传链路
124
+ - [MessageRender 消息渲染器](/components/message/message-render) — 顶层透传入口
@@ -0,0 +1,114 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ useFullScreen 将目标元素(或 document.documentElement)以浏览器原生全屏展示。 模块加载时一次性嗅探 requestFullscreen / webkitRequestFullscreen,返回 isSupported、只读 isFullScreen 与 enter/exit/toggle。 监听 fullscreenchange 同步 ESC 等外部退出;ChatContainer 侧栏全屏按钮使用此 composable。
5
+
6
+ ### 关联组件
7
+ - **chat-container** — 侧栏 .ai-full-screen-wrapper 全屏切换
8
+ - **tool-btn** — 全屏按钮通过插槽渲染 FullScreenIcon
9
+
10
+ ---
11
+ <!-- FULL DOC -->
12
+
13
+ # useFullScreen 全屏控制
14
+
15
+ > **分类**:composable
16
+
17
+ 基于浏览器原生 Fullscreen API 的全屏控制组合式函数。模块加载时一次性嗅探标准 API 与 `webkit` 前缀(兼容旧版 Safari),在组件作用域销毁时自动移除事件监听。
18
+
19
+ ## 工作原理
20
+
21
+ ```
22
+ useFullScreen(target?)
23
+
24
+ ├── resolveFullscreenApi()(模块级,仅执行一次)
25
+ │ requestFullscreen / webkitRequestFullscreen
26
+
27
+ ├── isSupported = !!fullscreenApi
28
+ ├── isFullScreen(readonly shallowRef,与浏览器真实状态同步)
29
+
30
+ ├── enter() → target.requestFullscreen()
31
+ ├── exit() → document.exitFullscreen()
32
+ ├── toggle() → isFullScreen ? exit() : enter()
33
+
34
+ └── document.addEventListener(fullscreenchange, syncState)
35
+ syncState:指定 target 时,仅当 fullscreenElement === target 视为全屏
36
+ onScopeDispose 时移除监听
37
+ ```
38
+
39
+ > **注意**:`enter()` 可能因缺少用户手势等原因被浏览器拒绝,内部会静默捕获异常,避免未处理的 Promise rejection。
40
+
41
+ ## 基础用法
42
+
43
+ ```vue
44
+ <template>
45
+ <div>
46
+ <div ref="panelRef" class="demo-panel">
47
+ <p>可全屏展示的面板内容</p>
48
+ </div>
49
+ <button :disabled="!isSupported" @click="enter">进入全屏</button>
50
+ <button :disabled="!isFullScreen" @click="exit">退出全屏</button>
51
+ <span>当前状态:{{ isFullScreen ? '全屏' : '窗口' }}</span>
52
+ </div>
53
+ </template>
54
+
55
+ <script setup lang="ts">
56
+ import { useTemplateRef } from 'vue';
57
+ import { useFullScreen } from '@blueking/chat-x';
58
+
59
+ const panelRef = useTemplateRef<HTMLElement>('panelRef');
60
+ const { isSupported, isFullScreen, enter, exit } = useFullScreen(panelRef);
61
+ </script>
62
+ ```
63
+
64
+ ## 在 ChatContainer 中的使用
65
+
66
+ `ChatContainer` 将侧栏包裹在 `.ai-full-screen-wrapper` 中,通过 `useFullScreen(fullScreenRef)` 控制侧栏全屏;Tab 栏 `#setting` 插槽内的 `ToolBtn` 使用自定义插槽渲染 `FullScreenIcon` / `UnFullScreenIcon`。
67
+
68
+ 详见 [ChatContainer 侧栏全屏](../components/setup/chat-container.md#侧栏全屏)。
69
+
70
+ ## API
71
+
72
+ ### 参数
73
+
74
+ | 参数名 | 类型 | 默认值 | 说明 |
75
+ | ------ | ---- | ------ | ---- |
76
+ | target | `MaybeRef<HTMLElement \| null>` | — | 需要全屏的目标元素;省略时回退到 `document.documentElement` |
77
+
78
+ ### 返回值
79
+
80
+ | 属性名 | 类型 | 说明 |
81
+ | ------ | ---- | ---- |
82
+ | isSupported | `boolean` | 当前环境是否支持 Fullscreen API(SSR 或不支持时为 `false`) |
83
+ | isFullScreen | `Readonly<ShallowRef<boolean>>` | 只读响应式全屏状态;与浏览器真实状态同步(含 ESC 退出) |
84
+ | enter | `() => Promise<void>` | 进入全屏;已全屏或不受支持时无操作 |
85
+ | exit | `() => Promise<void>` | 退出全屏;当前无全屏元素时无操作 |
86
+ | toggle | `() => void` | 切换全屏状态 |
87
+
88
+ ## 类型定义
89
+
90
+ ```typescript
91
+ import { useFullScreen } from '@blueking/chat-x';
92
+ import type { MaybeRef, Readonly, ShallowRef } from 'vue';
93
+
94
+ type UseFullScreenReturn = {
95
+ isSupported: boolean;
96
+ isFullScreen: Readonly<ShallowRef<boolean>>;
97
+ enter: () => Promise<void>;
98
+ exit: () => Promise<void>;
99
+ toggle: () => void;
100
+ };
101
+
102
+ // 调用签名
103
+ declare function useFullScreen(target?: MaybeRef<HTMLElement | null>): UseFullScreenReturn;
104
+ ```
105
+
106
+ ## 使用场景
107
+
108
+ - `ChatContainer` 侧栏执行情况 / 自定义 Tab 区域全屏查看
109
+ - 任意需要将局部 DOM 区域以浏览器原生全屏展示的交互面板
110
+
111
+ ## 关联组件
112
+
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; UserMessage 等通过 injectGlobalConfig 读取 supportUpload。
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` 共享**全局展示相关配置**(当前主要为是否支持上传 `supportUpload`)。与 Teleport 插槽 ID 无关。
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
- ├── useGlobalConfig({ supportUpload: computed(() => props.supportUpload ?? false) })
23
- │ └── provide(GLOBAL_CONFIG_TOKEN, { supportUpload })
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 变量说明