@blueking/chat-x 0.0.51-beta.5 → 0.0.52-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -8
- package/dist/ag-ui/types/contents.d.ts +2 -0
- package/dist/ag-ui/types/messages.d.ts +6 -1
- package/dist/common/constants.d.ts +2 -0
- package/dist/components/ai-buttons/add-menu-btn/add-menu-btn.vue.d.ts +24 -0
- package/dist/components/chat-content/collapsible-content/collapsible-content.vue.d.ts +28 -0
- package/dist/components/chat-content/file-content/upload-file-item.vue.d.ts +5 -2
- package/dist/components/chat-content/file-content/upload-image-item.vue.d.ts +1 -0
- package/dist/components/chat-content/flow-agent-content/use-flow-node-actions.d.ts +1 -1
- package/dist/components/chat-input/ai-slash-input/ai-slash-input.vue.d.ts +21 -10
- package/dist/components/chat-input/ai-slash-input/command.d.ts +6 -3
- package/dist/components/chat-input/ai-slash-input/constants.d.ts +2 -0
- package/dist/components/chat-input/ai-slash-input/use-menu-trigger.d.ts +17 -0
- package/dist/components/chat-input/build-default-placeholder.d.ts +9 -3
- package/dist/components/chat-input/chat-input.vue.d.ts +30 -18
- package/dist/components/chat-input/input-menu/constants.d.ts +60 -0
- package/dist/components/chat-input/input-menu/index.d.ts +4 -0
- package/dist/components/chat-input/input-menu/input-menu-option.vue.d.ts +14 -0
- package/dist/components/chat-input/input-menu/input-menu-panel.vue.d.ts +17 -0
- package/dist/components/chat-input/input-menu/use-input-menu.d.ts +22 -0
- package/dist/components/chat-input/model-selector/types.d.ts +3 -2
- package/dist/components/chat-message/message-container/message-container.vue.d.ts +1 -1
- package/dist/components/chat-message/user-message/user-message.vue.d.ts +1 -1
- package/dist/components/mention/create-mention-tippy.d.ts +27 -0
- package/dist/components/mention/index.d.ts +4 -0
- package/dist/components/{chat-input/ai-slash-input/ai-prompt-list/ai-prompt-list.vue.d.ts → mention/mention-popover.vue.d.ts} +3 -2
- package/dist/components/{chat-input/ai-slash-input/ai-skill-list/ai-skill-list.vue.d.ts → mention/mention-tag.vue.d.ts} +7 -3
- package/dist/components/{chat-input/ai-slash-input/ai-slash-menu/ai-slash-menu.vue.d.ts → mention/mention-text.vue.d.ts} +3 -3
- package/dist/components/resource-icon/index.d.ts +1 -0
- package/dist/components/resource-icon/resource-icon.vue.d.ts +11 -0
- package/dist/composables/index.d.ts +1 -0
- package/dist/composables/use-artifact-preview.d.ts +5 -2
- package/dist/composables/use-common.d.ts +0 -9
- package/dist/composables/use-global-config.d.ts +4 -0
- package/dist/composables/use-input-mention.d.ts +13 -0
- package/dist/composables/use-message-group.d.ts +1011 -72
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/input.d.ts +21 -0
- package/dist/icons/menu-item.d.ts +22 -0
- package/dist/index.css +1 -1
- package/dist/index.js +4953 -4429
- package/dist/index.js.map +1 -1
- package/dist/lang/lang.d.ts +13 -3
- package/dist/mcp/generated/docs/activity-message.md +3 -3
- package/dist/mcp/generated/docs/add-menu-btn.md +91 -0
- package/dist/mcp/generated/docs/ai-slash-input.md +72 -26
- package/dist/mcp/generated/docs/assistant-message.md +7 -1
- package/dist/mcp/generated/docs/chat-container.md +45 -6
- package/dist/mcp/generated/docs/chat-input.md +327 -483
- package/dist/mcp/generated/docs/collapsible-content.md +78 -0
- package/dist/mcp/generated/docs/constants.md +36 -3
- package/dist/mcp/generated/docs/execution-summary.md +1 -23
- package/dist/mcp/generated/docs/file-artifact-panel.md +24 -5
- package/dist/mcp/generated/docs/file-content.md +4 -0
- package/dist/mcp/generated/docs/file-upload-btn.md +15 -12
- package/dist/mcp/generated/docs/flow-agent-content.md +10 -12
- package/dist/mcp/generated/docs/input-menu-panel.md +166 -0
- package/dist/mcp/generated/docs/mention-tag.md +83 -0
- package/dist/mcp/generated/docs/mention-text.md +86 -0
- package/dist/mcp/generated/docs/message-container.md +1 -1
- package/dist/mcp/generated/docs/message-render.md +1 -1
- package/dist/mcp/generated/docs/message-tools.md +15 -4
- package/dist/mcp/generated/docs/messages.md +3 -0
- package/dist/mcp/generated/docs/model-selector.md +4 -2
- package/dist/mcp/generated/docs/overflow-tips.md +3 -3
- package/dist/mcp/generated/docs/resource-icon.md +102 -0
- package/dist/mcp/generated/docs/text-content.md +7 -3
- package/dist/mcp/generated/docs/theme.md +27 -35
- package/dist/mcp/generated/docs/use-artifact-preview.md +7 -3
- package/dist/mcp/generated/docs/use-command-selection.md +1 -1
- package/dist/mcp/generated/docs/use-container-scroll.md +2 -1
- package/dist/mcp/generated/docs/use-flow-node-actions.md +8 -15
- package/dist/mcp/generated/docs/use-global-config.md +11 -4
- package/dist/mcp/generated/docs/use-input-mention.md +119 -0
- package/dist/mcp/generated/docs/use-menu-keydown.md +15 -16
- package/dist/mcp/generated/docs/use-message-group.md +3 -6
- package/dist/mcp/generated/docs/user-message.md +39 -17
- package/dist/mcp/generated/index.json +233 -81
- package/dist/types/editor.d.ts +0 -29
- package/dist/types/index.d.ts +1 -0
- package/dist/types/input-menu.d.ts +46 -0
- package/dist/utils/artifact-tags.d.ts +36 -0
- package/dist/utils/collect-message-artifacts.d.ts +14 -0
- package/dist/utils/file.d.ts +3 -3
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/upload-file.d.ts +6 -1
- package/package.json +3 -2
- package/skills/blueking-chat-x/SKILL.md +143 -0
- package/skills/blueking-chat-x/references/_index.md +153 -0
- package/skills/blueking-chat-x/references/components/activity-layout.md +134 -0
- package/skills/blueking-chat-x/references/components/activity-message.md +486 -0
- package/skills/blueking-chat-x/references/components/add-menu-btn.md +88 -0
- package/skills/blueking-chat-x/references/components/ai-image.md +230 -0
- package/skills/blueking-chat-x/references/components/ai-loading.md +131 -0
- package/skills/blueking-chat-x/references/components/ai-selection.md +439 -0
- package/skills/blueking-chat-x/references/components/ai-slash-input.md +102 -0
- package/skills/blueking-chat-x/references/components/animation-text.md +202 -0
- package/skills/blueking-chat-x/references/components/assistant-message.md +504 -0
- package/skills/blueking-chat-x/references/components/chat-container.md +912 -0
- package/skills/blueking-chat-x/references/components/chat-input.md +614 -0
- package/skills/blueking-chat-x/references/components/cite-content.md +142 -0
- package/skills/blueking-chat-x/references/components/code-content.md +211 -0
- package/skills/blueking-chat-x/references/components/collapsible-content.md +76 -0
- package/skills/blueking-chat-x/references/components/common-error-content.md +73 -0
- package/skills/blueking-chat-x/references/components/content-render.md +233 -0
- package/skills/blueking-chat-x/references/components/delete-tool.md +191 -0
- package/skills/blueking-chat-x/references/components/desc-panel.md +162 -0
- package/skills/blueking-chat-x/references/components/detail-section.md +91 -0
- package/skills/blueking-chat-x/references/components/execution-summary.md +150 -0
- package/skills/blueking-chat-x/references/components/file-artifact-panel.md +307 -0
- package/skills/blueking-chat-x/references/components/file-content.md +340 -0
- package/skills/blueking-chat-x/references/components/file-icon.md +109 -0
- package/skills/blueking-chat-x/references/components/file-upload-btn.md +162 -0
- package/skills/blueking-chat-x/references/components/flow-agent-content.md +266 -0
- package/skills/blueking-chat-x/references/components/flow-agent-node-detail.md +236 -0
- package/skills/blueking-chat-x/references/components/highlight-keyword.md +146 -0
- package/skills/blueking-chat-x/references/components/image-content.md +182 -0
- package/skills/blueking-chat-x/references/components/image-preview-group.md +184 -0
- package/skills/blueking-chat-x/references/components/image-preview.md +226 -0
- package/skills/blueking-chat-x/references/components/info-message.md +144 -0
- package/skills/blueking-chat-x/references/components/input-attachment.md +49 -0
- package/skills/blueking-chat-x/references/components/input-info-alert.md +42 -0
- package/skills/blueking-chat-x/references/components/input-menu-panel.md +162 -0
- package/skills/blueking-chat-x/references/components/interrupt-message.md +212 -0
- package/skills/blueking-chat-x/references/components/key-value-content.md +128 -0
- package/skills/blueking-chat-x/references/components/knowledge-rag-content.md +122 -0
- package/skills/blueking-chat-x/references/components/latex-content.md +200 -0
- package/skills/blueking-chat-x/references/components/loading-message.md +192 -0
- package/skills/blueking-chat-x/references/components/markdown-content.md +232 -0
- package/skills/blueking-chat-x/references/components/mention-tag.md +79 -0
- package/skills/blueking-chat-x/references/components/mention-text.md +83 -0
- package/skills/blueking-chat-x/references/components/mermaid-content.md +189 -0
- package/skills/blueking-chat-x/references/components/message-container.md +645 -0
- package/skills/blueking-chat-x/references/components/message-loading.md +118 -0
- package/skills/blueking-chat-x/references/components/message-render.md +327 -0
- package/skills/blueking-chat-x/references/components/message-time.md +177 -0
- package/skills/blueking-chat-x/references/components/message-tools.md +427 -0
- package/skills/blueking-chat-x/references/components/model-selector.md +157 -0
- package/skills/blueking-chat-x/references/components/preview-toolbar.md +42 -0
- package/skills/blueking-chat-x/references/components/questions-container.md +85 -0
- package/skills/blueking-chat-x/references/components/reasoning-message.md +232 -0
- package/skills/blueking-chat-x/references/components/reference-content.md +135 -0
- package/skills/blueking-chat-x/references/components/reference-doc-content.md +109 -0
- package/skills/blueking-chat-x/references/components/resource-icon.md +98 -0
- package/skills/blueking-chat-x/references/components/scroll-btn.md +159 -0
- package/skills/blueking-chat-x/references/components/selection-footer.md +78 -0
- package/skills/blueking-chat-x/references/components/selection-question.md +88 -0
- package/skills/blueking-chat-x/references/components/shortcut-btn.md +204 -0
- package/skills/blueking-chat-x/references/components/shortcut-btns.md +266 -0
- package/skills/blueking-chat-x/references/components/shortcut-render.md +424 -0
- package/skills/blueking-chat-x/references/components/simple-table.md +101 -0
- package/skills/blueking-chat-x/references/components/text-content.md +80 -0
- package/skills/blueking-chat-x/references/components/tool-approval-card.md +183 -0
- package/skills/blueking-chat-x/references/components/tool-btn.md +317 -0
- package/skills/blueking-chat-x/references/components/tool-message.md +235 -0
- package/skills/blueking-chat-x/references/components/toolcall-render.md +348 -0
- package/skills/blueking-chat-x/references/components/user-feedback.md +233 -0
- package/skills/blueking-chat-x/references/components/user-message.md +444 -0
- package/skills/blueking-chat-x/references/components/user-question-answered-card.md +104 -0
- package/skills/blueking-chat-x/references/components/user-question-card.md +231 -0
- package/skills/blueking-chat-x/references/components/user-question-choice.md +105 -0
- package/skills/blueking-chat-x/references/components/user-question-option.md +42 -0
- package/skills/blueking-chat-x/references/components/vnode-renderer.md +122 -0
- package/skills/blueking-chat-x/references/composables/use-animation-text.md +196 -0
- package/skills/blueking-chat-x/references/composables/use-artifact-preview.md +235 -0
- package/skills/blueking-chat-x/references/composables/use-clipboard.md +203 -0
- package/skills/blueking-chat-x/references/composables/use-command-selection.md +150 -0
- package/skills/blueking-chat-x/references/composables/use-container-scroll.md +57 -0
- package/skills/blueking-chat-x/references/composables/use-custom-tab.md +158 -0
- package/skills/blueking-chat-x/references/composables/use-flow-node-actions.md +164 -0
- package/skills/blueking-chat-x/references/composables/use-full-screen.md +112 -0
- package/skills/blueking-chat-x/references/composables/use-global-config.md +155 -0
- package/skills/blueking-chat-x/references/composables/use-input-mention.md +115 -0
- package/skills/blueking-chat-x/references/composables/use-menu-keydown.md +161 -0
- package/skills/blueking-chat-x/references/composables/use-message-group.md +244 -0
- package/skills/blueking-chat-x/references/composables/use-observer-visible-list.md +188 -0
- package/skills/blueking-chat-x/references/composables/use-parent-scrolling.md +46 -0
- package/skills/blueking-chat-x/references/directives/index.md +61 -0
- package/skills/blueking-chat-x/references/directives/overflow-tips.md +205 -0
- package/skills/blueking-chat-x/references/icons/index.md +185 -0
- package/skills/blueking-chat-x/references/plugins/index.md +56 -0
- package/skills/blueking-chat-x/references/plugins/markdown-container.md +55 -0
- package/skills/blueking-chat-x/references/plugins/markdown-latex.md +205 -0
- package/skills/blueking-chat-x/references/plugins/markdown-mermaid.md +247 -0
- package/skills/blueking-chat-x/references/theme/theme.md +423 -0
- package/skills/blueking-chat-x/references/types/constants.md +340 -0
- package/skills/blueking-chat-x/references/types/index.md +120 -0
- package/skills/blueking-chat-x/references/types/interrupt.md +379 -0
- package/skills/blueking-chat-x/references/types/messages.md +556 -0
- package/skills/blueking-chat-x/references/types/schema.md +91 -0
- package/skills/blueking-chat-x/references/utils/index.md +196 -0
- package/skills/blueking-chat-x/scripts/generate-references.mjs +536 -0
- package/dist/components/chat-input/ai-slash-editor/ai-slash-editor.vue.d.ts +0 -28
- package/dist/components/chat-input/ai-slash-editor/theme.d.ts +0 -24
- package/dist/mcp/generated/docs/ai-prompt-list.md +0 -45
- package/dist/mcp/generated/docs/ai-skill-list.md +0 -75
- package/dist/mcp/generated/docs/ai-slash-editor.md +0 -43
- package/dist/mcp/generated/docs/ai-slash-menu.md +0 -42
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# useCommandSelection
|
|
2
|
+
|
|
3
|
+
> 导入:`import { useCommandSelection } from '@blueking/chat-x'` | since 1.0.0
|
|
4
|
+
|
|
5
|
+
useCommandSelection 无参数,返回 commandSelection、docSnapshot、GetCursorPosition、GetDocSnapshot。 GetCursorPosition 写入光标行列;GetDocSnapshot 将当前文档快照写入 docSnapshot,供外部 modelValue 与编辑器比对同步。 仅在 AiSlashInput(@ 菜单插入与 modelValue 同步)内部使用。
|
|
6
|
+
|
|
7
|
+
**关联**:chat-input(AiSlashInput 内部使用)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# useCommandSelection 光标位置追踪
|
|
12
|
+
|
|
13
|
+
> **分类**:composable
|
|
14
|
+
|
|
15
|
+
为 `edix` 富文本编辑器提供光标位置追踪能力的组合式函数。内部封装一个 `EditorCommand`,由编辑器调用后将光标的行列信息存入响应式变量,供后续编辑命令(如插入 tag、删除关键词)精确定位。
|
|
16
|
+
|
|
17
|
+
> 该 composable 仅在 `AiSlashInput` 内部使用,属于编辑器底层基础设施,**通常无需直接调用**。
|
|
18
|
+
|
|
19
|
+
## 实现原理
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
editor.command(GetCursorPosition)
|
|
23
|
+
│ edix 编辑器将 (doc, selection) 注入 EditorCommand
|
|
24
|
+
│
|
|
25
|
+
└── GetCursorPosition(doc, selection)
|
|
26
|
+
const [, focus] = selection // selection = [anchor, focus]
|
|
27
|
+
const [line, column] = focus // focus = [lineIndex, columnIndex]
|
|
28
|
+
commandSelection.value = { column, line }
|
|
29
|
+
↓
|
|
30
|
+
commandSelection(shallowRef,初始值 { column: 0, line: 0 })
|
|
31
|
+
|
|
32
|
+
editor.command(GetDocSnapshot)
|
|
33
|
+
└── GetDocSnapshot(doc)
|
|
34
|
+
docSnapshot.value = doc // 当前文档快照,用于与 props.modelValue 比对
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**使用时机**:
|
|
38
|
+
|
|
39
|
+
- 在 `@` 资源插入流程中,先执行 `GetCursorPosition` 快照当前光标,再据此计算删除范围和插入位置。
|
|
40
|
+
- 在外部 `modelValue` 变化时,先执行 `GetDocSnapshot` 取得编辑器当前文档,与 `docToString(modelValue)` 比对,决定是否 `ReplaceAll` 同步。
|
|
41
|
+
|
|
42
|
+
## 概念演示
|
|
43
|
+
|
|
44
|
+
`commandSelection` 追踪编辑器光标的 `{ line, column }` 位置(行从 0 开始,column 为字符偏移量)。以下用原生 textarea 模拟等价的位置信息:
|
|
45
|
+
|
|
46
|
+
> 实际使用时,由 `editor.command(GetCursorPosition)` 触发写入,而非手动计算。
|
|
47
|
+
|
|
48
|
+
## 在 AiSlashInput 中的实际用法
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { watch } from 'vue';
|
|
52
|
+
|
|
53
|
+
const { commandSelection, GetCursorPosition, GetDocSnapshot, docSnapshot } = useCommandSelection();
|
|
54
|
+
|
|
55
|
+
// 用户从 @xxx 菜单中选择资源时:
|
|
56
|
+
const insertTagAtCursor = (tag: IInputMenuItem) => {
|
|
57
|
+
editor.command(GetCursorPosition);
|
|
58
|
+
const { column, line } = commandSelection.value;
|
|
59
|
+
editor.command(DeleteTag, [line, column - keyword.value.length - 1], [line, column]);
|
|
60
|
+
editor.command(InsertTag, [line, column], tag);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// 外部 modelValue 变化时,与编辑器文档对齐(简化示意;需已存在 editor、props、text、docToString)
|
|
64
|
+
watch(
|
|
65
|
+
() => props.modelValue,
|
|
66
|
+
() => {
|
|
67
|
+
editor.command(GetDocSnapshot);
|
|
68
|
+
if (docToString(docSnapshot.value || []) !== docToString(text.value || [])) {
|
|
69
|
+
editor.command(ReplaceAll, docToString(text.value || []) as unknown as string);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{ deep: false },
|
|
73
|
+
);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API
|
|
77
|
+
|
|
78
|
+
### 参数
|
|
79
|
+
|
|
80
|
+
无。`useCommandSelection()` 不接受任何参数。
|
|
81
|
+
|
|
82
|
+
### 返回值
|
|
83
|
+
|
|
84
|
+
| 属性名 | 类型 | 初始值 | 说明 |
|
|
85
|
+
| ------------------- | ---------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
86
|
+
| `commandSelection` | `ShallowRef<{ column: number; line: number }>` | `{ column: 0, line: 0 }` | 存储最近一次执行 `GetCursorPosition` 时的光标行列位置 |
|
|
87
|
+
| `docSnapshot` | `ShallowRef<DocFragment>` | `[]` | 存储最近一次执行 `GetDocSnapshot` 时的文档快照 |
|
|
88
|
+
| `GetCursorPosition` | `EditorCommand<[]>` | — | 编辑器命令,由 `editor.command(GetCursorPosition)` 触发,将当前光标写入 `commandSelection` |
|
|
89
|
+
| `GetDocSnapshot` | `EditorCommand<[]>` | — | 编辑器命令,由 `editor.command(GetDocSnapshot)` 触发,将当前文档写入 `docSnapshot` |
|
|
90
|
+
|
|
91
|
+
## 类型说明
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// EditorCommand:edix 编辑器的命令签名
|
|
95
|
+
type EditorCommand<A extends unknown[]> = (
|
|
96
|
+
doc: DocFragment,
|
|
97
|
+
selection: SelectionSnapshot, // [[anchorLine, anchorColumn], [focusLine, focusColumn]]
|
|
98
|
+
...args: A
|
|
99
|
+
) => Transaction | void;
|
|
100
|
+
|
|
101
|
+
// useCommandSelection 返回值
|
|
102
|
+
interface UseCommandSelectionReturn {
|
|
103
|
+
commandSelection: ShallowRef<{ column: number; line: number }>;
|
|
104
|
+
docSnapshot: ShallowRef<DocFragment>;
|
|
105
|
+
GetCursorPosition: EditorCommand<[]>;
|
|
106
|
+
GetDocSnapshot: EditorCommand<[]>;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 实现源码
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { shallowRef } from 'vue';
|
|
114
|
+
|
|
115
|
+
import type { EditorCommand } from '../edix';
|
|
116
|
+
import type { DocFragment } from '../edix/doc/types';
|
|
117
|
+
|
|
118
|
+
export const useCommandSelection = () => {
|
|
119
|
+
const commandSelection = shallowRef<{ column: number; line: number }>({ column: 0, line: 0 });
|
|
120
|
+
const docSnapshot = shallowRef<DocFragment>([]);
|
|
121
|
+
|
|
122
|
+
const GetCursorPosition: EditorCommand<[]> = (_doc, selection) => {
|
|
123
|
+
const [, focus] = selection;
|
|
124
|
+
const [line, column] = focus;
|
|
125
|
+
commandSelection.value = { column, line };
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const GetDocSnapshot: EditorCommand<[]> = doc => {
|
|
129
|
+
docSnapshot.value = doc;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
commandSelection,
|
|
134
|
+
docSnapshot,
|
|
135
|
+
GetCursorPosition,
|
|
136
|
+
GetDocSnapshot,
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 注意事项
|
|
142
|
+
|
|
143
|
+
1. **只读命令**:`GetCursorPosition` 不返回 `Transaction`,不修改编辑器文档内容,仅记录位置
|
|
144
|
+
2. **异步快照**:`commandSelection` 在 `editor.command(GetCursorPosition)` 执行后**同步**更新,下一行代码即可安全读取
|
|
145
|
+
3. **`shallowRef` 而非 `ref`**:对象引用替换触发响应式,内部字段修改不触发(此处每次整体替换,无影响)
|
|
146
|
+
4. **仅适用于 edix 编辑器**:`GetCursorPosition` / `GetDocSnapshot` 依赖 edix 的文档与选区格式,不适用于原生 contenteditable 或其他富文本库
|
|
147
|
+
|
|
148
|
+
## 关联组件
|
|
149
|
+
|
|
150
|
+
- [ChatInput](../components/input/chat-input) — AiSlashInput 子模块使用
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# useContainerScroll
|
|
2
|
+
|
|
3
|
+
> 导入:`import { useContainerScrollConsumer, useContainerScrollProvider } from '@blueking/chat-x'` | since 1.0.0
|
|
4
|
+
|
|
5
|
+
useContainerScrollProvider 在滚动容器与底部锚点上绑定 IntersectionObserver、scroll、wheel,提供 isScrollBottom、scrollBottomHeight、autoScrollEnabled、jumpToBottom、toScrollBottom/toScrollTop 及防抖「返回底部」按钮状态。 toScrollBottom 缺省按距底部距离自动选择行为:超过 INSTANT_SCROLL_DISTANCE(600px)时瞬时贴底,否则平滑滚动,避免切换会话时出现长距离平滑滚动动画。 useContainerScrollConsumer 通过 inject 在子组件中获取同一套控制,无需 props 透传。 典型用于流式输出时仅在用户位于底部时自动滚底。MessageContainer 与 ScrollBtn 配合使用。
|
|
6
|
+
|
|
7
|
+
**关联**:message-container(Provider 挂载于消息列表滚动区域)、scroll-btn(使用 debouncedShowScrollBottomBtn 与 toScrollBottom)、chat-container(组合消息区与输入区时的整体布局上下文)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# useContainerScroll 容器滚动
|
|
12
|
+
|
|
13
|
+
> **分类**:composable
|
|
14
|
+
|
|
15
|
+
为消息容器提供滚动控制的组合式函数对,通过 **Provider/Consumer** 模式在父子组件间共享滚动状态。
|
|
16
|
+
|
|
17
|
+
- `useContainerScrollProvider`:在容器组件中调用,创建滚动控制并通过 `provide` 向下共享
|
|
18
|
+
- `useContainerScrollConsumer`:在任意后代组件中调用,通过 `inject` 获取滚动控制
|
|
19
|
+
|
|
20
|
+
## 工作原理
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
useContainerScrollProvider(containerRef, bottomRef)
|
|
24
|
+
│
|
|
25
|
+
├── IntersectionObserver 监听 bottomRef
|
|
26
|
+
│ 可见 → isScrollBottom=true, scrollBottomHeight=0, autoScrollEnabled=true
|
|
27
|
+
│ 不可见 → isScrollBottom=false, calculateScrollBottom()
|
|
28
|
+
│
|
|
29
|
+
├── scroll 事件(passive)→ calculateScrollBottom()
|
|
30
|
+
│ scrollBottomHeight = max(0, scrollHeight - scrollTop - clientHeight)
|
|
31
|
+
│
|
|
32
|
+
├── wheel 事件(passive)→ deltaY < 0 时 autoScrollEnabled=false
|
|
33
|
+
│ (用户向上滚动时暂停自动滚动)
|
|
34
|
+
│
|
|
35
|
+
├── jumpToBottom() → autoScrollEnabled=true + container.scrollTop = scrollHeight(瞬时)
|
|
36
|
+
├── toScrollBottom(behavior?) → autoScrollEnabled=true;
|
|
37
|
+
│ behavior 缺省时:距底部 > INSTANT_SCROLL_DISTANCE(600) → jumpToBottom()
|
|
38
|
+
│ 否则 / 显式 'smooth' → bottomRef.scrollIntoView({ behavior:'smooth', block:'end' })
|
|
39
|
+
├── toScrollTop() → containerRef.scrollTo({ top:0, behavior:'smooth' })
|
|
40
|
+
│
|
|
41
|
+
└── provide(CONTAINER_SCROLL_TOKEN, computed(() => ({
|
|
42
|
+
autoScrollEnabled: autoScrollEnabled.value, // 解包为 boolean
|
|
43
|
+
isScrollBottom, // ShallowRef<boolean>(保持响应式)
|
|
44
|
+
scrollBottomHeight, // ShallowRef<number>(保持响应式)
|
|
45
|
+
debouncedShowScrollBottomBtn, // customRef,防抖显示返回底部按钮
|
|
46
|
+
jumpToBottom,
|
|
47
|
+
toScrollBottom,
|
|
48
|
+
toScrollTop,
|
|
49
|
+
})))
|
|
50
|
+
|
|
51
|
+
useContainerScrollConsumer()
|
|
52
|
+
└── inject(CONTAINER_SCROLL_TOKEN) → ComputedRef<ContainerScrollData> | undefined
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
> **注意**:Consumer 获得的 `ComputedRef` 中,`isScrollBottom` 和 `scrollBottomHeight` 是 `ShallowRef` 对象(非解包值),需要通过 `.value` 访问。
|
|
56
|
+
|
|
57
|
+
## 渲染示例
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# useCustomTab
|
|
2
|
+
|
|
3
|
+
> 导入:`import { useCustomTabConsumer, useCustomTabProvider } from '@blueking/chat-x'` | since 1.0.0
|
|
4
|
+
|
|
5
|
+
useCustomTabProvider 返回 tabs、selectedTab、isCollapse 及 add/ensure/remove/selectCustomTab,并通过 provide 共享;可选 onTabChange 在切换时拉取数据、可选 collapsed 注入受控折叠态 ref。 ensureCustomTab 只挂载/合并元信息,不展开侧栏、不主动切换选中;addCustomTab 会展开并选中。 未被主动切换过时,选中态默认跟随 Tab 栏首位(order 最小),如常驻的「文件产物」。 useCustomTabConsumer 在后代注入同一套 API,常用于侧栏动态节点详情等。EXECUTION_TAB_NAME 标识默认「执行情况」Tab。 ChatContainer 侧栏集成 Provider 与 Tab UI。
|
|
6
|
+
|
|
7
|
+
**关联**:chat-container(Provider 与侧栏 Tab 主场景)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# useCustomTab 自定义 Tab 管理
|
|
12
|
+
|
|
13
|
+
> **分类**:composable
|
|
14
|
+
|
|
15
|
+
Provider/Consumer 模式的自定义 Tab 管理,用于 `ChatContainer` 侧边栏的 Tab 动态管理。Provider 在 `ChatContainer` 中创建,Consumer 在任意后代组件中注入使用。
|
|
16
|
+
|
|
17
|
+
## 函数签名
|
|
18
|
+
|
|
19
|
+
### useCustomTabProvider
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
function useCustomTabProvider<T extends Record<string, unknown>>(options: {
|
|
23
|
+
// 侧栏折叠态;由容器传入受控 ref(如 ChatContainer 的 v-model:asideCollapsed),缺省内部自持
|
|
24
|
+
collapsed?: Ref<boolean>;
|
|
25
|
+
// 执行情况 Tab 是否展示,缺省 true;传 getter 以保持响应式
|
|
26
|
+
executionTabVisible?: () => boolean | undefined;
|
|
27
|
+
onTabChange?: (tab: CustomTab<T>) => void;
|
|
28
|
+
}): {
|
|
29
|
+
tabs: ShallowRef<CustomTab<T>[]>;
|
|
30
|
+
displayTabs: ComputedRef<CustomTab<T>[]>;
|
|
31
|
+
selectedTab: Ref<CustomTab<T>>;
|
|
32
|
+
isCollapse: Ref<boolean>;
|
|
33
|
+
addCustomTab: (tab: CustomTab<T>) => void;
|
|
34
|
+
ensureCustomTab: (tab: CustomTab<T>) => void;
|
|
35
|
+
removeCustomTab: (tabName: string) => void;
|
|
36
|
+
selectCustomTab: (tab: CustomTab<T>) => void;
|
|
37
|
+
resetCustomTab: () => void;
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### useCustomTabConsumer
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
function useCustomTabConsumer<T extends Record<string, unknown>>():
|
|
45
|
+
| undefined
|
|
46
|
+
| {
|
|
47
|
+
tabs: ShallowRef<CustomTab<T>[]>;
|
|
48
|
+
displayTabs: ComputedRef<CustomTab<T>[]>;
|
|
49
|
+
selectedTab: ShallowRef<CustomTab<T> | null>;
|
|
50
|
+
addCustomTab: (tab: CustomTab<T>) => void;
|
|
51
|
+
ensureCustomTab: (tab: CustomTab<T>) => void;
|
|
52
|
+
removeCustomTab: (tabName: string) => void;
|
|
53
|
+
selectCustomTab: (tab: CustomTab<T>) => void;
|
|
54
|
+
resetCustomTab: () => void;
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 使用示例
|
|
59
|
+
|
|
60
|
+
### Provider(容器组件)
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { useCustomTabProvider, EXECUTION_TAB_NAME } from '@blueking/chat-x';
|
|
64
|
+
|
|
65
|
+
const { tabs, selectedTab, isCollapse, addCustomTab, ensureCustomTab, removeCustomTab, selectCustomTab, resetCustomTab } =
|
|
66
|
+
useCustomTabProvider({
|
|
67
|
+
onTabChange: async tab => {
|
|
68
|
+
// Tab 切换时加载数据
|
|
69
|
+
const data = await fetchTabData(tab.name);
|
|
70
|
+
return data;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Consumer(后代组件)
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { useCustomTabConsumer } from '@blueking/chat-x';
|
|
79
|
+
|
|
80
|
+
const tabManager = useCustomTabConsumer();
|
|
81
|
+
|
|
82
|
+
// 添加一个自定义 Tab(展开侧栏并选中)
|
|
83
|
+
tabManager?.addCustomTab({
|
|
84
|
+
name: 'node-detail-123',
|
|
85
|
+
label: '节点详情',
|
|
86
|
+
data: {
|
|
87
|
+
component: NodeDetailComponent,
|
|
88
|
+
props: { nodeId: '123' },
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// 仅确保 Tab 存在(不展开、不切换选中)—— 如常驻挂上文件产物 Tab
|
|
93
|
+
tabManager?.ensureCustomTab({
|
|
94
|
+
name: 'file-artifact',
|
|
95
|
+
label: '文件产物',
|
|
96
|
+
closable: false,
|
|
97
|
+
order: -1,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// 移除 Tab
|
|
101
|
+
tabManager?.removeCustomTab('node-detail-123');
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 内置常量
|
|
105
|
+
|
|
106
|
+
| 常量名 | 值 | 说明 |
|
|
107
|
+
| -------------------- | ------------- | ------------------------------------------ |
|
|
108
|
+
| `EXECUTION_TAB_NAME` | `'execution'` | 执行情况 Tab 的固定标识 |
|
|
109
|
+
| `DEFAULT_TAB_ORDER` | `100` | Tab 默认排序权重;执行情况固定为 `0` |
|
|
110
|
+
| `CUSTOM_TAB_TOKEN` | `Symbol` | provide/inject 注入 Token |
|
|
111
|
+
|
|
112
|
+
## 返回值说明
|
|
113
|
+
|
|
114
|
+
| 属性/方法名 | 类型 | 说明 |
|
|
115
|
+
| --------------- | --------------------------- | ------------------------------------------------- |
|
|
116
|
+
| tabs | `ShallowRef<CustomTab[]>` | 所有 Tab 列表(含默认的执行情况 Tab,保留隐藏项) |
|
|
117
|
+
| displayTabs | `ComputedRef<CustomTab[]>` | Tab 栏实际展示列表:过滤 `visible === false`,按 `order` 升序稳定排序 |
|
|
118
|
+
| selectedTab | `Ref<CustomTab>` | 当前选中的 Tab;未被主动切换过时跟随 Tab 栏首位,选中项被隐藏时自动回退到首个可见 Tab |
|
|
119
|
+
| isCollapse | `Ref<boolean>` | 侧边栏折叠状态;传入 `collapsed` 时即该受控 ref(读写都作用于外部),否则为内部状态;`addCustomTab` 时自动设为 `false` |
|
|
120
|
+
| addCustomTab | `(tab: CustomTab) => void` | 添加/合并 Tab,**展开侧栏并选中**目标 Tab |
|
|
121
|
+
| ensureCustomTab | `(tab: CustomTab) => void` | 添加/合并 Tab,**不展开、不主动切换选中**;用于常驻挂载(如文件产物) |
|
|
122
|
+
| removeCustomTab | `(tabName: string) => void` | 移除指定 Tab |
|
|
123
|
+
| selectCustomTab | `(tab: CustomTab) => void` | 切换到指定 Tab,触发 `onTabChange` 回调 |
|
|
124
|
+
| resetCustomTab | `() => void` | 重置为仅保留「执行情况」Tab、折叠侧栏并选中默认 Tab;`ChatContainer` 在卸载时调用,避免残留自定义 Tab |
|
|
125
|
+
|
|
126
|
+
## 类型定义
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface CustomTab<T = Record<string, unknown>> {
|
|
130
|
+
label: string;
|
|
131
|
+
name: string;
|
|
132
|
+
/** 可与 `component` / `props` 并列;用于侧栏「在对话中定位」与主消息 `message.uid` 对齐 */
|
|
133
|
+
data?: T & { messageUid?: string };
|
|
134
|
+
/** 排序权重,升序,越小越靠前;缺省 100,执行情况默认 0 */
|
|
135
|
+
order?: number;
|
|
136
|
+
/** 是否在 Tab 栏展示,缺省 true;false 时仍可被程序化选中,但内容不渲染、会自动切到首个可见 Tab */
|
|
137
|
+
visible?: boolean;
|
|
138
|
+
/** 是否可关闭,缺省 true;执行情况强制不可关闭 */
|
|
139
|
+
closable?: boolean;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 设计特点
|
|
144
|
+
|
|
145
|
+
- `tabs` 使用 `shallowRef`,`addCustomTab` 通过展开新数组触发更新,避免 `UnwrapRef<T>` 类型问题
|
|
146
|
+
- 默认的「执行情况」Tab 始终存在且不可关闭,`order` 固定 `0`;可通过 `executionTabVisible` 配置显隐
|
|
147
|
+
- `displayTabs` 负责「过滤显隐 + 按 `order` 排序」;原始 `tabs` 仍保留全部 Tab 供程序化选中与查找
|
|
148
|
+
- 排序为稳定排序,`order` 相同的 Tab 保持插入先后顺序
|
|
149
|
+
- 选中的 Tab 被配置隐藏时,内容不再渲染,自动切换到首个可见 Tab
|
|
150
|
+
- `addCustomTab` 同时展开侧边栏(`isCollapse = false`)并在 `nextTick` 后自动选中目标 Tab;同名 Tab 合并更新
|
|
151
|
+
- `ensureCustomTab` 与 `addCustomTab` 共用合并逻辑,但不改 `isCollapse`、自身不切换 `selectedTab`;适合「常驻挂载文件产物 Tab」等场景
|
|
152
|
+
- 默认选中跟随 Tab 栏首位:只要没调用过 `selectCustomTab` / `addCustomTab`,挂上更靠前(`order` 更小)的 Tab 就会成为选中项,因此常驻的「文件产物」(`order: -1`)是侧栏默认面板;一旦主动切换过便不再跟随。`resetCustomTab` 会重置该标记
|
|
153
|
+
- 折叠态支持受控:传入 `collapsed` 后 Provider 不再自持状态,内部展开动作直接写回该 ref,容器即可通过 `v-model` 把状态交给外部判断
|
|
154
|
+
|
|
155
|
+
## 关联组件
|
|
156
|
+
|
|
157
|
+
- [ChatContainer](../components/setup/chat-container) — 侧栏 Tab 与自定义面板
|
|
158
|
+
- [useArtifactPreview](./use-artifact-preview) — 文件产物 Tab:初始化 `ensureCustomTab` 常驻挂载,点击卡片时 `addCustomTab`
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# useFlowNodeActions
|
|
2
|
+
|
|
3
|
+
> 未从包入口导出:内部实现 | since 2.0.0
|
|
4
|
+
|
|
5
|
+
useFlowNodeActions 接收 onInterruptResume 与 openNodeDetail,返回 getNodeActions 与 isNodePending。 失败节点按 retryable/skippable 展示重试/跳过,详情恒在末尾;点击后进入 pending 防重复提交, 以 task_id:node_id:retry 为键自动收敛;点击 resume 时不传 interrupt。 hideResumeActions 为 true 时只返回详情,覆盖 Share 分享态与侧栏「执行情况」面板两类只读场景。
|
|
6
|
+
|
|
7
|
+
**关联**:flow-agent-content(FlowAgentContent 内部消费,驱动节点行尾按钮组渲染)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# useFlowNodeActions 节点行尾操作
|
|
12
|
+
|
|
13
|
+
> **分类**:composable
|
|
14
|
+
|
|
15
|
+
将 FlowAgent 节点行尾的「详情(打开侧栏)」与「重试 / 跳过(回传 Agent resume)」聚合为统一的声明式操作列表。`FlowAgentContent` 只需遍历 `getNodeActions` 返回值渲染按钮,显隐与点击行为均收敛于此 composable。
|
|
16
|
+
|
|
17
|
+
源码:`src/components/chat-content/flow-agent-content/use-flow-node-actions.ts`
|
|
18
|
+
|
|
19
|
+
## 函数签名
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
function useFlowNodeActions(options: {
|
|
23
|
+
/** 隐藏重试 / 跳过等交互式 resume 操作(分享态、侧栏执行情况面板等只读场景,仅保留「详情」查看入口) */
|
|
24
|
+
hideResumeActions?: Ref<boolean>;
|
|
25
|
+
/** resume 回调(与第三方审批取消同一回调,按 payload.operation 分流) */
|
|
26
|
+
onInterruptResume: Ref<OnInterruptResume | undefined>;
|
|
27
|
+
/** 打开节点详情侧栏(复用 useFlowTab 的能力) */
|
|
28
|
+
openNodeDetail: (task: BkFlowTask, node: BkFlowNode) => void;
|
|
29
|
+
}): {
|
|
30
|
+
getNodeActions: (task: FlowTaskVM, node: FlowNodeVM) => FlowNodeActionVM[];
|
|
31
|
+
/** 当前节点是否有进行中的 resume 操作(供视图层常驻显示按钮组) */
|
|
32
|
+
isNodePending: (task: FlowTaskVM, node: FlowNodeVM) => boolean;
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 返回值:FlowNodeActionVM
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
type FlowNodeActionId =
|
|
40
|
+
| 'detail'
|
|
41
|
+
| InterruptResumeOperation.FlowNodeRetry
|
|
42
|
+
| InterruptResumeOperation.FlowNodeSkip;
|
|
43
|
+
|
|
44
|
+
interface FlowNodeActionVM {
|
|
45
|
+
/** 是否禁用点击(任一 resume 操作进行中时,重试 / 跳过均禁用) */
|
|
46
|
+
disabled: boolean;
|
|
47
|
+
icon: Component;
|
|
48
|
+
id: FlowNodeActionId;
|
|
49
|
+
/** 国际化文案(进行中时切换为「重试中 / 跳过中」) */
|
|
50
|
+
label: string;
|
|
51
|
+
/** 是否处于进行中态:图标切换为 loading */
|
|
52
|
+
loading: boolean;
|
|
53
|
+
/** 因另一操作进行中而禁用时的 hover 提示 */
|
|
54
|
+
tooltip?: string;
|
|
55
|
+
run: () => void;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| 字段 | 说明 |
|
|
60
|
+
| ---------- | -------------------------------------------------------------- |
|
|
61
|
+
| `disabled` | 禁用点击;resume 进行中时重试 / 跳过均为 `true`,详情恒为 `false` |
|
|
62
|
+
| `icon` | 按钮图标组件(`loading` 时由上层切换为 Loading 组件) |
|
|
63
|
+
| `id` | 唯一标识,用于 `v-for` key |
|
|
64
|
+
| `label` | 国际化文案;进行中为「重试中 / 跳过中」 |
|
|
65
|
+
| `loading` | 本操作进行中时为 `true` |
|
|
66
|
+
| `tooltip` | 被另一操作阻塞时的 hover 提示(如「任务正在重试中,不可跳过」) |
|
|
67
|
+
| `run` | 点击执行(详情或 resume);进行中重复调用被内部忽略 |
|
|
68
|
+
|
|
69
|
+
## 操作显隐规则
|
|
70
|
+
|
|
71
|
+
| 操作 | `id` | 显隐条件 | 点击行为 |
|
|
72
|
+
| ---- | ------------------ | ------------------------------------------ | --------------------------------------------- |
|
|
73
|
+
| 重试 | `flow_node_retry` | `convergedState === 'failed'` 且 `retryable`,且 `hideResumeActions` 为 `false` | 调用 `onInterruptResume`,**不传** `interrupt` |
|
|
74
|
+
| 跳过 | `flow_node_skip` | `convergedState === 'failed'` 且 `skippable`,且 `hideResumeActions` 为 `false` | 同上 |
|
|
75
|
+
| 详情 | `detail` | 始终(不受 `hideResumeActions` 影响) | 调用 `openNodeDetail(task.raw, node.raw)` |
|
|
76
|
+
|
|
77
|
+
展示顺序:重试 → 跳过 → 详情。
|
|
78
|
+
|
|
79
|
+
> **只读场景过滤**:`hideResumeActions` 为 `true` 时,`getNodeActions` 直接过滤掉重试 / 跳过,仅返回「详情」查看入口,用于放开查看、禁止交互的场景。`FlowAgentContent` 目前把两类只读场景并入该入参:
|
|
80
|
+
>
|
|
81
|
+
> - `RenderMode.Share` 分享态
|
|
82
|
+
> - 侧栏「执行情况」面板内(`ExecutionSummary` 通过 `EXECUTION_PANEL_TOKEN` 提供上下文,组件用 `useExecutionPanelInject` 读取)
|
|
83
|
+
|
|
84
|
+
## pending 态与防重复提交
|
|
85
|
+
|
|
86
|
+
点击重试或跳过后:
|
|
87
|
+
|
|
88
|
+
1. 以 `task_id:node_id:retry` 为键写入 `pendingMap`,同一节点仅允许一个进行中的 resume 操作
|
|
89
|
+
2. 进行中按钮:`loading: true`、`disabled: true`、`label` 切换为「重试中 / 跳过中」
|
|
90
|
+
3. 另一 resume 按钮:`disabled: true`,`tooltip` 给出阻塞原因
|
|
91
|
+
4. 详情按钮:不受影响
|
|
92
|
+
5. `isNodePending(task, node)` 返回 `true`,供视图层添加 `is-pending` class 常驻显示按钮组
|
|
93
|
+
6. 后端推送新状态且 `node.retry` 变化时,pending 键自动失效,按钮恢复可用
|
|
94
|
+
|
|
95
|
+
## resume 负载格式
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// 重试
|
|
99
|
+
onInterruptResume?.({
|
|
100
|
+
operation: InterruptResumeOperation.FlowNodeRetry,
|
|
101
|
+
payload: { node_id: node.id, task_id: task.task_id },
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// 跳过
|
|
105
|
+
onInterruptResume?.({
|
|
106
|
+
operation: InterruptResumeOperation.FlowNodeSkip,
|
|
107
|
+
payload: { node_id: node.id, task_id: task.task_id },
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 使用示例
|
|
112
|
+
|
|
113
|
+
`FlowAgentContent` 内部用法(业务侧通常通过 `MessageRender` 传入 `onInterruptResume`,无需直接调用本 composable):
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { toRef } from 'vue';
|
|
117
|
+
import { useFlowNodeActions } from '@blueking/chat-x';
|
|
118
|
+
// 或相对路径:'./use-flow-node-actions'
|
|
119
|
+
|
|
120
|
+
// 是否处于侧栏「执行情况」面板内;缺省 false,即对话流内渲染
|
|
121
|
+
// useExecutionPanelInject 来自内部 src/composables/use-common.ts,未从包入口导出
|
|
122
|
+
const isInExecutionPanel = useExecutionPanelInject();
|
|
123
|
+
|
|
124
|
+
const { getNodeActions, isNodePending } = useFlowNodeActions({
|
|
125
|
+
// 分享态与侧栏执行情况面板均只读:过滤重试 / 跳过,仅保留详情
|
|
126
|
+
hideResumeActions: computed(() => renderMode.value === RenderMode.Share || isInExecutionPanel),
|
|
127
|
+
onInterruptResume: toRef(props, 'onInterruptResume'),
|
|
128
|
+
openNodeDetail,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// 模板中
|
|
132
|
+
// :class="{ 'is-pending': isNodePending(task, node) }"
|
|
133
|
+
// v-for="action in getNodeActions(task, node)" :key="action.id"
|
|
134
|
+
// :class="{ 'is-disabled': action.disabled }"
|
|
135
|
+
// v-tippy="action.tooltip ? { content: action.tooltip } : { content: '' }"
|
|
136
|
+
// @click.stop="handleActionClick(action)" // 禁用态拦截,避免重复提交
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 扩展新操作
|
|
140
|
+
|
|
141
|
+
在 `RESUME_ACTION_DEFS` 注册表中追加一项即可,需声明 `visible` 与 `operation` 枚举:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const RESUME_ACTION_DEFS: FlowNodeResumeActionDef[] = [
|
|
145
|
+
// 现有:重试、跳过
|
|
146
|
+
{
|
|
147
|
+
blockedTip: () => t('另一操作进行中的提示'),
|
|
148
|
+
icon: MyIcon,
|
|
149
|
+
id: InterruptResumeOperation.MyNewOp, // 需先在 InterruptResumeOperation 扩展
|
|
150
|
+
label: () => t('新操作'),
|
|
151
|
+
pendingLabel: () => t('新操作进行中'),
|
|
152
|
+
visible: node => /* 自定义显隐 */,
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
同时在 `interrupt.ts` 扩展 `InterruptResumeOperation` 与 `FlowNodeResume` 联合类型。
|
|
158
|
+
|
|
159
|
+
## 关联文档
|
|
160
|
+
|
|
161
|
+
- [FlowAgentContent 执行内容](/components/agent/flow-agent-content) — 消费方组件
|
|
162
|
+
- [中断类型 Interrupt](/types/interrupt) — `InterruptResumeOperation`、`FlowNodeResume`、`OnInterruptResume`
|
|
163
|
+
- [ActivityMessage 活动消息](/components/message/activity-message) — `onInterruptResume` 透传链路
|
|
164
|
+
- [MessageRender 消息渲染器](/components/message/message-render) — 顶层透传入口
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# useFullScreen
|
|
2
|
+
|
|
3
|
+
> 导入:`import { useFullScreen } from '@blueking/chat-x'` | since 2.0.0
|
|
4
|
+
|
|
5
|
+
useFullScreen 将目标元素(或 document.documentElement)以浏览器原生全屏展示。 模块加载时一次性嗅探 requestFullscreen / webkitRequestFullscreen,返回 isSupported、只读 isFullScreen 与 enter/exit/toggle。 监听 fullscreenchange 同步 ESC 等外部退出;ChatContainer 侧栏全屏按钮使用此 composable。
|
|
6
|
+
|
|
7
|
+
**关联**:chat-container(侧栏 .ai-full-screen-wrapper 全屏切换)、tool-btn(全屏按钮通过插槽渲染 FullScreenIcon)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# useFullScreen 全屏控制
|
|
12
|
+
|
|
13
|
+
> **分类**:composable
|
|
14
|
+
|
|
15
|
+
基于浏览器原生 Fullscreen API 的全屏控制组合式函数。模块加载时一次性嗅探标准 API 与 `webkit` 前缀(兼容旧版 Safari),在组件作用域销毁时自动移除事件监听。
|
|
16
|
+
|
|
17
|
+
## 工作原理
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
useFullScreen(target?)
|
|
21
|
+
│
|
|
22
|
+
├── resolveFullscreenApi()(模块级,仅执行一次)
|
|
23
|
+
│ requestFullscreen / webkitRequestFullscreen
|
|
24
|
+
│
|
|
25
|
+
├── isSupported = !!fullscreenApi
|
|
26
|
+
├── isFullScreen(readonly shallowRef,与浏览器真实状态同步)
|
|
27
|
+
│
|
|
28
|
+
├── enter() → target.requestFullscreen()
|
|
29
|
+
├── exit() → document.exitFullscreen()
|
|
30
|
+
├── toggle() → isFullScreen ? exit() : enter()
|
|
31
|
+
│
|
|
32
|
+
└── document.addEventListener(fullscreenchange, syncState)
|
|
33
|
+
syncState:指定 target 时,仅当 fullscreenElement === target 视为全屏
|
|
34
|
+
onScopeDispose 时移除监听
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> **注意**:`enter()` 可能因缺少用户手势等原因被浏览器拒绝,内部会静默捕获异常,避免未处理的 Promise rejection。
|
|
38
|
+
|
|
39
|
+
## 基础用法
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<template>
|
|
43
|
+
<div>
|
|
44
|
+
<div ref="panelRef" class="demo-panel">
|
|
45
|
+
<p>可全屏展示的面板内容</p>
|
|
46
|
+
</div>
|
|
47
|
+
<button :disabled="!isSupported" @click="enter">进入全屏</button>
|
|
48
|
+
<button :disabled="!isFullScreen" @click="exit">退出全屏</button>
|
|
49
|
+
<span>当前状态:{{ isFullScreen ? '全屏' : '窗口' }}</span>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import { useTemplateRef } from 'vue';
|
|
55
|
+
import { useFullScreen } from '@blueking/chat-x';
|
|
56
|
+
|
|
57
|
+
const panelRef = useTemplateRef<HTMLElement>('panelRef');
|
|
58
|
+
const { isSupported, isFullScreen, enter, exit } = useFullScreen(panelRef);
|
|
59
|
+
</script>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 在 ChatContainer 中的使用
|
|
63
|
+
|
|
64
|
+
`ChatContainer` 将侧栏包裹在 `.ai-full-screen-wrapper` 中,通过 `useFullScreen(fullScreenRef)` 控制侧栏全屏;Tab 栏 `#setting` 插槽内的 `ToolBtn` 使用自定义插槽渲染 `FullScreenIcon` / `UnFullScreenIcon`。
|
|
65
|
+
|
|
66
|
+
详见 [ChatContainer 侧栏全屏](../components/setup/chat-container.md#侧栏全屏)。
|
|
67
|
+
|
|
68
|
+
## API
|
|
69
|
+
|
|
70
|
+
### 参数
|
|
71
|
+
|
|
72
|
+
| 参数名 | 类型 | 默认值 | 说明 |
|
|
73
|
+
| ------ | ---- | ------ | ---- |
|
|
74
|
+
| target | `MaybeRef<HTMLElement \| null>` | — | 需要全屏的目标元素;省略时回退到 `document.documentElement` |
|
|
75
|
+
|
|
76
|
+
### 返回值
|
|
77
|
+
|
|
78
|
+
| 属性名 | 类型 | 说明 |
|
|
79
|
+
| ------ | ---- | ---- |
|
|
80
|
+
| isSupported | `boolean` | 当前环境是否支持 Fullscreen API(SSR 或不支持时为 `false`) |
|
|
81
|
+
| isFullScreen | `Readonly<ShallowRef<boolean>>` | 只读响应式全屏状态;与浏览器真实状态同步(含 ESC 退出) |
|
|
82
|
+
| enter | `() => Promise<void>` | 进入全屏;已全屏或不受支持时无操作 |
|
|
83
|
+
| exit | `() => Promise<void>` | 退出全屏;当前无全屏元素时无操作 |
|
|
84
|
+
| toggle | `() => void` | 切换全屏状态 |
|
|
85
|
+
|
|
86
|
+
## 类型定义
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { useFullScreen } from '@blueking/chat-x';
|
|
90
|
+
import type { MaybeRef, Readonly, ShallowRef } from 'vue';
|
|
91
|
+
|
|
92
|
+
type UseFullScreenReturn = {
|
|
93
|
+
isSupported: boolean;
|
|
94
|
+
isFullScreen: Readonly<ShallowRef<boolean>>;
|
|
95
|
+
enter: () => Promise<void>;
|
|
96
|
+
exit: () => Promise<void>;
|
|
97
|
+
toggle: () => void;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// 调用签名
|
|
101
|
+
declare function useFullScreen(target?: MaybeRef<HTMLElement | null>): UseFullScreenReturn;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 使用场景
|
|
105
|
+
|
|
106
|
+
- `ChatContainer` 侧栏执行情况 / 自定义 Tab 区域全屏查看
|
|
107
|
+
- 任意需要将局部 DOM 区域以浏览器原生全屏展示的交互面板
|
|
108
|
+
|
|
109
|
+
## 关联组件
|
|
110
|
+
|
|
111
|
+
- [ChatContainer](../components/setup/chat-container.md) — 内置侧栏全屏按钮
|
|
112
|
+
- [ToolBtn](../components/feedback/tool-btn.md) — 全屏按钮自定义插槽
|