@blueking/chat-x 0.0.5 → 0.0.6
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/mcp/generated/docs/activity-message.md +428 -0
- package/dist/mcp/generated/docs/ai-image.md +227 -0
- package/dist/mcp/generated/docs/ai-loading.md +129 -0
- package/dist/mcp/generated/docs/ai-selection.md +436 -0
- package/dist/mcp/generated/docs/animation-text.md +199 -0
- package/dist/mcp/generated/docs/assistant-message.md +424 -0
- package/dist/mcp/generated/docs/chat-container.md +365 -0
- package/dist/mcp/generated/docs/chat-input.md +625 -0
- package/dist/mcp/generated/docs/cite-content.md +138 -0
- package/dist/mcp/generated/docs/code-content.md +199 -0
- package/dist/mcp/generated/docs/common-error-content.md +70 -0
- package/dist/mcp/generated/docs/constants.md +216 -0
- package/dist/mcp/generated/docs/content-render.md +238 -0
- package/dist/mcp/generated/docs/delete-tool.md +188 -0
- package/dist/mcp/generated/docs/desc-panel.md +139 -0
- package/dist/mcp/generated/docs/execution-summary.md +126 -0
- package/dist/mcp/generated/docs/file-content.md +300 -0
- package/dist/mcp/generated/docs/file-upload-btn.md +174 -0
- package/dist/mcp/generated/docs/flow-message.md +305 -0
- package/dist/mcp/generated/docs/highlight-keyword.md +144 -0
- package/dist/mcp/generated/docs/image-content.md +178 -0
- package/dist/mcp/generated/docs/image-preview-group.md +181 -0
- package/dist/mcp/generated/docs/image-preview.md +224 -0
- package/dist/mcp/generated/docs/info-message.md +124 -0
- package/dist/mcp/generated/docs/key-value-content.md +124 -0
- package/dist/mcp/generated/docs/latex-content.md +196 -0
- package/dist/mcp/generated/docs/loading-message.md +171 -0
- package/dist/mcp/generated/docs/markdown-content.md +186 -0
- package/dist/mcp/generated/docs/markdown-latex.md +208 -0
- package/dist/mcp/generated/docs/markdown-mermaid.md +250 -0
- package/dist/mcp/generated/docs/mermaid-content.md +185 -0
- package/dist/mcp/generated/docs/message-container.md +534 -0
- package/dist/mcp/generated/docs/message-render.md +329 -0
- package/dist/mcp/generated/docs/message-tools.md +376 -0
- package/dist/mcp/generated/docs/messages.md +472 -0
- package/dist/mcp/generated/docs/overflow-tips.md +209 -0
- package/dist/mcp/generated/docs/reasoning-message.md +233 -0
- package/dist/mcp/generated/docs/reference-content.md +132 -0
- package/dist/mcp/generated/docs/scroll-btn.md +155 -0
- package/dist/mcp/generated/docs/selection-footer.md +75 -0
- package/dist/mcp/generated/docs/shortcut-btn.md +202 -0
- package/dist/mcp/generated/docs/shortcut-btns.md +264 -0
- package/dist/mcp/generated/docs/shortcut-render.md +418 -0
- package/dist/mcp/generated/docs/text-content.md +74 -0
- package/dist/mcp/generated/docs/theme.md +388 -0
- package/dist/mcp/generated/docs/tool-btn.md +254 -0
- package/dist/mcp/generated/docs/tool-message.md +217 -0
- package/dist/mcp/generated/docs/toolcall-render.md +299 -0
- package/dist/mcp/generated/docs/use-animation-text.md +198 -0
- package/dist/mcp/generated/docs/use-clipboard.md +206 -0
- package/dist/mcp/generated/docs/use-command-selection.md +128 -0
- package/dist/mcp/generated/docs/use-container-scroll.md +56 -0
- package/dist/mcp/generated/docs/use-custom-tab.md +122 -0
- package/dist/mcp/generated/docs/use-global-config.md +154 -0
- package/dist/mcp/generated/docs/use-menu-keydown.md +164 -0
- package/dist/mcp/generated/docs/use-message-group.md +175 -0
- package/dist/mcp/generated/docs/use-observer-visible-list.md +189 -0
- package/dist/mcp/generated/docs/use-parent-scrolling.md +46 -0
- package/dist/mcp/generated/docs/user-feedback.md +229 -0
- package/dist/mcp/generated/docs/user-message.md +347 -0
- package/dist/mcp/generated/index.json +1311 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +42 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +43 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/get-component-doc.d.ts +19 -0
- package/dist/mcp/tools/get-component-doc.js +60 -0
- package/dist/mcp/tools/get-component-doc.js.map +1 -0
- package/dist/mcp/tools/list-components.d.ts +35 -0
- package/dist/mcp/tools/list-components.js +147 -0
- package/dist/mcp/tools/list-components.js.map +1 -0
- package/dist/mcp/tools/search-docs.d.ts +14 -0
- package/dist/mcp/tools/search-docs.js +82 -0
- package/dist/mcp/tools/search-docs.js.map +1 -0
- package/dist/mcp/utils/doc-loader.d.ts +35 -0
- package/dist/mcp/utils/doc-loader.js +64 -0
- package/dist/mcp/utils/doc-loader.js.map +1 -0
- package/package.json +5 -7
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
AiLoading 使用纯 CSS/SVG 动画(旋转环与脉冲星形)展示加载中,不依赖 bkui Loading。 多实例时需用 cloneVNode 等为渐变 id 加前缀避免冲突;支持 stopLoading 暂停动画。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **loading-message** — 列表末尾加载占位
|
|
8
|
+
- **reasoning-message** — 推理进行中的加载指示
|
|
9
|
+
- **activity-message** — 活动消息加载态指示
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
<!-- FULL DOC -->
|
|
13
|
+
|
|
14
|
+
# AiLoading AI 加载动画
|
|
15
|
+
|
|
16
|
+
> **层级**:原子组件 · **功能域**:辅助组件
|
|
17
|
+
|
|
18
|
+
AI 加载动画原子组件。由两层 SVG 叠加构成:外层旋转光环(带渐变弧线)+ 内层脉冲星形图标,两者共用同一套蓝→紫→粉渐变色。
|
|
19
|
+
|
|
20
|
+
## 组件结构
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
.ai-loading(inline-flex,position: relative,width/height 由 size prop 控制)
|
|
24
|
+
│ CSS 同时定义 width/height: 1em 兜底,inline style 优先
|
|
25
|
+
│
|
|
26
|
+
├── .ai-loading-ring(position: absolute,svg 100%×100%)
|
|
27
|
+
│ 旋转弧线:ai-loading-rotate 0.8s linear infinite
|
|
28
|
+
│ 渐变:#235DFA → #8A77EC → #EB8CEC(蓝 → 紫 → 粉)
|
|
29
|
+
│
|
|
30
|
+
└── .ai-loading-star(position: absolute,svg 100%×100%)
|
|
31
|
+
脉冲星形:ai-loading-pulse 0.8s ease-in-out infinite
|
|
32
|
+
关键帧:scale(0.5) → scale(1) → scale(0.5)(小→大→小)
|
|
33
|
+
渐变:同上
|
|
34
|
+
|
|
35
|
+
stopLoading=true → 根元素加 .ai-loading-stopped
|
|
36
|
+
→ .ai-loading-stopped .ai-loading-ring { animation-play-state: paused }
|
|
37
|
+
→ .ai-loading-stopped .ai-loading-star { animation-play-state: paused }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 基础用法
|
|
41
|
+
|
|
42
|
+
```vue
|
|
43
|
+
<template>
|
|
44
|
+
<AiLoading />
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<script setup lang="ts">
|
|
48
|
+
import { AiLoading } from '@blueking/chat-x';
|
|
49
|
+
</script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 自定义尺寸
|
|
53
|
+
|
|
54
|
+
通过 `size` 属性控制图标大小(单位 px),默认 `16`:
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<template>
|
|
58
|
+
<AiLoading />
|
|
59
|
+
<!-- 16px(默认) -->
|
|
60
|
+
<AiLoading :size="24" />
|
|
61
|
+
<AiLoading :size="32" />
|
|
62
|
+
<AiLoading :size="48" />
|
|
63
|
+
</template>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 暂停动画
|
|
67
|
+
|
|
68
|
+
`stopLoading` 为 `true` 时,组件根元素添加 `.ai-loading-stopped` class,两层动画同时进入 `paused` 状态(不移除元素,仅冻结帧):
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<template>
|
|
72
|
+
<AiLoading :stop-loading="isPaused" />
|
|
73
|
+
<button @click="isPaused = !isPaused">
|
|
74
|
+
{{ isPaused ? '恢复' : '暂停' }}
|
|
75
|
+
</button>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<script setup lang="ts">
|
|
79
|
+
import { ref } from 'vue';
|
|
80
|
+
import { AiLoading } from '@blueking/chat-x';
|
|
81
|
+
|
|
82
|
+
const isPaused = ref(false);
|
|
83
|
+
</script>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 多实例渐变隔离
|
|
87
|
+
|
|
88
|
+
每个 `AiLoading` 实例通过**模块级 `uid` 计数器**生成唯一的 SVG 渐变 ID:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
ai-loading-ring-{instanceId}
|
|
92
|
+
ai-loading-star-{instanceId}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
同一页面挂载多个实例时,渐变互不影响。ring 和 star 的 `instanceId` 始终相同(同一组件内),SVG `<path fill="url(#...)" />` 正确引用各自实例的渐变定义。
|
|
96
|
+
|
|
97
|
+
## 动画规格
|
|
98
|
+
|
|
99
|
+
| 层 | 动画名 | 时长 | 缓动 | 关键帧 |
|
|
100
|
+
| ------------------ | ------------------- | ---- | ----------- | --------------------------------------- |
|
|
101
|
+
| `.ai-loading-ring` | `ai-loading-rotate` | 0.8s | linear | `0deg → 360deg` 匀速旋转 |
|
|
102
|
+
| `.ai-loading-star` | `ai-loading-pulse` | 0.8s | ease-in-out | `0%/100%: scale(0.5)` → `50%: scale(1)` |
|
|
103
|
+
|
|
104
|
+
脉冲动画节奏:以**半尺寸**起始 → 膨胀至**全尺寸**(0.4s)→ 收缩回**半尺寸**(0.4s),循环往复。
|
|
105
|
+
|
|
106
|
+
## API
|
|
107
|
+
|
|
108
|
+
### Props
|
|
109
|
+
|
|
110
|
+
| 属性名 | 类型 | 默认值 | 说明 |
|
|
111
|
+
| ----------- | --------- | ------- | -------------------------------------------------- |
|
|
112
|
+
| size | `number` | `16` | 图标尺寸(px),应用为 inline style,覆盖 CSS 默认 |
|
|
113
|
+
| stopLoading | `boolean` | `false` | `true` 时两层动画均 `paused`,图标停在当前帧 |
|
|
114
|
+
|
|
115
|
+
## 使用场景
|
|
116
|
+
|
|
117
|
+
组件库内部以下场景自动使用 `AiLoading`:
|
|
118
|
+
|
|
119
|
+
| 使用方 | 触发时机 | 固定尺寸 |
|
|
120
|
+
| ------------------ | ---------------------------------------------- | --------- |
|
|
121
|
+
| `LoadingMessage` | 等待 AI 首次响应(loading 消息占位) | 18px |
|
|
122
|
+
| `ReasoningMessage` | `status` 为 `pending`/`streaming` 时(思考中) | 默认 16px |
|
|
123
|
+
| `ActivityMessage` | 活动消息加载状态 | 默认 16px |
|
|
124
|
+
|
|
125
|
+
## 关联组件
|
|
126
|
+
|
|
127
|
+
- [LoadingMessage](../molecular/loading-message.md) — 对话加载消息
|
|
128
|
+
- [ReasoningMessage](../molecular/reasoning-message.md) — 推理加载态
|
|
129
|
+
- [ActivityMessage](../molecular/activity-message.md) — 活动加载态
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
<!-- AI SUMMARY -->
|
|
2
|
+
## 快速了解
|
|
3
|
+
|
|
4
|
+
AiSelection 在 document 级监听文本选区,在选区附近弹出快捷操作菜单;每页建议只挂载一个实例。 通过 shortcuts、maxShortcutCount、offset 等配置菜单内容与布局,支持完全自定义 default 插槽与 Shadow DOM 场景。 常与 ChatInput 或业务侧联动,将选中文本作为追问上下文。
|
|
5
|
+
|
|
6
|
+
### 关联组件
|
|
7
|
+
- **shortcut-btn** — 弹窗内快捷指令按钮/菜单项由该原子组件渲染
|
|
8
|
+
- **chat-input** — 划词结果常回填或触发与输入框联动的快捷指令
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
<!-- FULL DOC -->
|
|
12
|
+
|
|
13
|
+
# AiSelection AI 划词选择弹窗
|
|
14
|
+
|
|
15
|
+
> **层级**:分子组件 · **功能域**:输入交互
|
|
16
|
+
|
|
17
|
+
AI 划词选择组件,监听用户在页面中的文本选区,在选区附近弹出快捷操作菜单。支持自定义快捷指令列表、数量限制、垂直偏移以及完全自定义插槽内容。
|
|
18
|
+
|
|
19
|
+
> **注意**:`AiSelection` 通过 `document.addEventListener` 监听全局事件(`selectionchange`、`mouseup`、`mousedown`、`scroll`),**同一页面中只应挂载一个实例**,避免多实例同时响应导致事件重复和弹窗叠加。
|
|
20
|
+
|
|
21
|
+
## 工作原理
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
用户选中文本
|
|
25
|
+
↓ mouseup(200ms 防抖)/ selectionchange(300ms 防抖)
|
|
26
|
+
获取选区文本 & 坐标 → 计算弹窗位置
|
|
27
|
+
↓
|
|
28
|
+
通过 <Teleport to="body"> 将弹窗渲染到 <body> 末尾
|
|
29
|
+
↓
|
|
30
|
+
用户点击快捷指令 → 触发 selectShortcut 事件 → 关闭弹窗
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
弹窗渲染在 `<body>` 顶层,不受父级 `overflow: hidden` / `z-index` 影响,定位坐标基于视口(`position: fixed`)。
|
|
34
|
+
|
|
35
|
+
## 弹窗关闭时机
|
|
36
|
+
|
|
37
|
+
| 触发条件 | 说明 |
|
|
38
|
+
| ------------------ | -------------------------------- |
|
|
39
|
+
| 点击弹窗外部区域 | `mousedown` 事件,弹窗外任意位置 |
|
|
40
|
+
| 滚动包含选区的容器 | `scroll` 事件捕获阶段 |
|
|
41
|
+
| 窗口大小改变 | `window.resize` |
|
|
42
|
+
| 窗口失去焦点 | `window.blur` |
|
|
43
|
+
| 点击快捷指令 | 触发后立即关闭并清除选区 |
|
|
44
|
+
|
|
45
|
+
## 基础用法
|
|
46
|
+
|
|
47
|
+
不传 `shortcuts` 时,使用内置默认快捷指令"问问小鲸"(`id: 'ai-chat'`):
|
|
48
|
+
|
|
49
|
+
```vue
|
|
50
|
+
<template>
|
|
51
|
+
<AiSelection v-model:visible="selectionVisible" />
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script setup lang="ts">
|
|
55
|
+
import { ref } from 'vue';
|
|
56
|
+
import { AiSelection } from '@blueking/chat-x';
|
|
57
|
+
|
|
58
|
+
const selectionVisible = ref(false);
|
|
59
|
+
</script>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**渲染效果**(选中下方文字后弹出快捷操作菜单)
|
|
63
|
+
|
|
64
|
+
## 自定义快捷指令
|
|
65
|
+
|
|
66
|
+
通过 `shortcuts` 属性传入自定义快捷指令列表:
|
|
67
|
+
|
|
68
|
+
```vue
|
|
69
|
+
<template>
|
|
70
|
+
<AiSelection
|
|
71
|
+
v-model:visible="selectionVisible"
|
|
72
|
+
:shortcuts="shortcuts"
|
|
73
|
+
@select-shortcut="handleSelectShortcut"
|
|
74
|
+
@selection-change="handleSelectionChange"
|
|
75
|
+
/>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<script setup lang="ts">
|
|
79
|
+
import { ref } from 'vue';
|
|
80
|
+
import { AiSelection, type Shortcut } from '@blueking/chat-x';
|
|
81
|
+
|
|
82
|
+
const selectionVisible = ref(false);
|
|
83
|
+
|
|
84
|
+
const shortcuts: Shortcut[] = [
|
|
85
|
+
{ id: 'ai-chat', name: '问问小鲸' },
|
|
86
|
+
{ id: 'translate', name: '翻译' },
|
|
87
|
+
{ id: 'explain', name: '解释' },
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
const handleSelectShortcut = (shortcut: Shortcut, selectedText: string) => {
|
|
91
|
+
console.log('触发指令:', shortcut.name, '选中文本:', selectedText);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const handleSelectionChange = (text: string) => {
|
|
95
|
+
console.log('选区变化:', text);
|
|
96
|
+
};
|
|
97
|
+
</script>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**渲染效果**(选中文字后弹出 3 个快捷操作按钮)
|
|
101
|
+
|
|
102
|
+
## 快捷指令数量限制
|
|
103
|
+
|
|
104
|
+
当快捷指令数量超过 `maxShortcutCount`(默认 `3`)时,多余的指令会收起到「更多」菜单(点击 `›` 箭头展开)。
|
|
105
|
+
|
|
106
|
+
### `maxShortcutCount = 3`(默认)
|
|
107
|
+
|
|
108
|
+
6 个指令中前 3 个直接展示,其余 3 个收起:
|
|
109
|
+
|
|
110
|
+
```vue
|
|
111
|
+
<template>
|
|
112
|
+
<AiSelection
|
|
113
|
+
v-model:visible="selectionVisible"
|
|
114
|
+
:shortcuts="shortcuts"
|
|
115
|
+
/>
|
|
116
|
+
</template>
|
|
117
|
+
|
|
118
|
+
<script setup lang="ts">
|
|
119
|
+
import { ref } from 'vue';
|
|
120
|
+
import { AiSelection, type Shortcut } from '@blueking/chat-x';
|
|
121
|
+
|
|
122
|
+
const selectionVisible = ref(false);
|
|
123
|
+
|
|
124
|
+
const shortcuts: Shortcut[] = [
|
|
125
|
+
{ id: 'ai-chat', name: '问问小鲸' },
|
|
126
|
+
{ id: 'translate', name: '翻译' },
|
|
127
|
+
{ id: 'explain', name: '解释' },
|
|
128
|
+
{ id: 'summarize', name: '总结' },
|
|
129
|
+
{ id: 'improve', name: '改进' },
|
|
130
|
+
{ id: 'code', name: '生成代码' },
|
|
131
|
+
];
|
|
132
|
+
</script>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**渲染效果**(展示 3 个,其余 3 个收起到「更多」菜单)
|
|
136
|
+
|
|
137
|
+
### `maxShortcutCount = 5`
|
|
138
|
+
|
|
139
|
+
前 5 个直接展示,仅最后 1 个收起:
|
|
140
|
+
|
|
141
|
+
```vue
|
|
142
|
+
<AiSelection v-model:visible="selectionVisible" :shortcuts="shortcuts" :max-shortcut-count="5" />
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**渲染效果**(展示 5 个,仅「生成代码」收起)
|
|
146
|
+
|
|
147
|
+
## 带图标的快捷指令
|
|
148
|
+
|
|
149
|
+
`icon` 属性支持三种形式:
|
|
150
|
+
|
|
151
|
+
| 类型 | 说明 | 示例 |
|
|
152
|
+
| --------------------------------- | --------------- | -------------------------------- |
|
|
153
|
+
| `string`(emoji) | 直接渲染文本 | `'🌐'` |
|
|
154
|
+
| `string`(HTTP URL) | 渲染为 `<img>` | `'https://example.com/icon.svg'` |
|
|
155
|
+
| `VNode \| (c: typeof h) => VNode` | 渲染为 Vue 组件 | `ThinkingIcon`(内置图标组件) |
|
|
156
|
+
|
|
157
|
+
```vue
|
|
158
|
+
<script setup lang="ts">
|
|
159
|
+
import { h } from 'vue';
|
|
160
|
+
import { AiSelection, type Shortcut } from '@blueking/chat-x';
|
|
161
|
+
|
|
162
|
+
const shortcuts: Shortcut[] = [
|
|
163
|
+
{
|
|
164
|
+
id: 'ai-chat',
|
|
165
|
+
name: '问问小鲸',
|
|
166
|
+
// VNode 渲染函数
|
|
167
|
+
icon: c => c('span', { style: 'font-size: 14px;' }, '🐳'),
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: 'translate',
|
|
171
|
+
name: '翻译',
|
|
172
|
+
icon: '🌐', // Emoji 字符串
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: 'search',
|
|
176
|
+
name: '搜索',
|
|
177
|
+
icon: 'https://example.com/search-icon.svg', // URL(渲染为 img)
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
</script>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 事件回调
|
|
184
|
+
|
|
185
|
+
`selectShortcut` 在用户点击快捷指令后触发,携带指令对象和选中文本;`selectionChange` 在选区文字内容变化时触发:
|
|
186
|
+
|
|
187
|
+
```vue
|
|
188
|
+
<template>
|
|
189
|
+
<div>
|
|
190
|
+
<p>选中文字后点击快捷指令,观察下方回调信息。</p>
|
|
191
|
+
|
|
192
|
+
<AiSelection
|
|
193
|
+
v-model:visible="selectionVisible"
|
|
194
|
+
:shortcuts="shortcuts"
|
|
195
|
+
@select-shortcut="handleSelectShortcut"
|
|
196
|
+
@selection-change="handleSelectionChange"
|
|
197
|
+
/>
|
|
198
|
+
|
|
199
|
+
<div
|
|
200
|
+
v-if="selectedInfo.shortcut"
|
|
201
|
+
class="callback-info"
|
|
202
|
+
>
|
|
203
|
+
<p>触发指令:{{ selectedInfo.shortcut }}</p>
|
|
204
|
+
<p>选中文本:{{ selectedInfo.text }}</p>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
</template>
|
|
208
|
+
|
|
209
|
+
<script setup lang="ts">
|
|
210
|
+
import { ref } from 'vue';
|
|
211
|
+
import { AiSelection, type Shortcut } from '@blueking/chat-x';
|
|
212
|
+
|
|
213
|
+
const selectionVisible = ref(false);
|
|
214
|
+
const selectedInfo = ref({ shortcut: '', text: '' });
|
|
215
|
+
|
|
216
|
+
const shortcuts: Shortcut[] = [
|
|
217
|
+
{ id: 'ai-chat', name: '问问小鲸' },
|
|
218
|
+
{ id: 'translate', name: '翻译' },
|
|
219
|
+
{ id: 'explain', name: '解释' },
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
const handleSelectShortcut = (shortcut: Shortcut, selectedText: string) => {
|
|
223
|
+
selectedInfo.value = { shortcut: shortcut.name, text: selectedText };
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const handleSelectionChange = (text: string) => {
|
|
227
|
+
console.log('选区变化:', text);
|
|
228
|
+
};
|
|
229
|
+
</script>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**渲染效果**(点击快捷指令后下方显示回调信息)
|
|
233
|
+
|
|
234
|
+
## 自定义垂直偏移
|
|
235
|
+
|
|
236
|
+
`offset` 控制弹窗与选区之间的垂直距离(单位 px),默认 `10`。弹窗优先显示在选区**上方**,空间不足时自动显示在**下方**:
|
|
237
|
+
|
|
238
|
+
```vue
|
|
239
|
+
<!-- 间距 20px -->
|
|
240
|
+
<AiSelection v-model:visible="selectionVisible" :offset="20" />
|
|
241
|
+
|
|
242
|
+
<!-- 紧贴选区(间距 0) -->
|
|
243
|
+
<AiSelection v-model:visible="selectionVisible" :offset="0" />
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## 自定义插槽
|
|
247
|
+
|
|
248
|
+
默认插槽替换整个弹窗内容区,插槽参数 `shortcuts` 为**完整**快捷指令列表(未经 `maxShortcutCount` 截断):
|
|
249
|
+
|
|
250
|
+
```vue
|
|
251
|
+
<template>
|
|
252
|
+
<AiSelection
|
|
253
|
+
v-model:visible="selectionVisible"
|
|
254
|
+
:shortcuts="shortcuts"
|
|
255
|
+
>
|
|
256
|
+
<template #default="{ shortcuts }">
|
|
257
|
+
<div class="my-menu">
|
|
258
|
+
<button
|
|
259
|
+
v-for="shortcut in shortcuts"
|
|
260
|
+
:key="shortcut.id"
|
|
261
|
+
@click="handleClick(shortcut)"
|
|
262
|
+
>
|
|
263
|
+
{{ shortcut.name }}
|
|
264
|
+
</button>
|
|
265
|
+
</div>
|
|
266
|
+
</template>
|
|
267
|
+
</AiSelection>
|
|
268
|
+
</template>
|
|
269
|
+
|
|
270
|
+
<script setup lang="ts">
|
|
271
|
+
import { ref } from 'vue';
|
|
272
|
+
import { AiSelection, type Shortcut } from '@blueking/chat-x';
|
|
273
|
+
|
|
274
|
+
const selectionVisible = ref(false);
|
|
275
|
+
|
|
276
|
+
const shortcuts: Shortcut[] = [
|
|
277
|
+
{ id: 'ai-chat', name: '问问小鲸' },
|
|
278
|
+
{ id: 'translate', name: '翻译' },
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
const handleClick = (shortcut: Shortcut) => {
|
|
282
|
+
const text = window.getSelection()?.toString() || '';
|
|
283
|
+
console.log(shortcut.name, text);
|
|
284
|
+
};
|
|
285
|
+
</script>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
> **注意**:使用默认插槽后,`maxShortcutCount` 不再生效,「更多」菜单也不会出现,需要自行处理超出逻辑。
|
|
289
|
+
|
|
290
|
+
## 排除区域
|
|
291
|
+
|
|
292
|
+
通过 `excludeSelectors` 指定 CSS 选择器列表,当选区位于这些选择器匹配的元素内部时,弹窗不会弹出。适用于代码块、表单输入等不需要划词弹窗的区域:
|
|
293
|
+
|
|
294
|
+
```vue
|
|
295
|
+
<template>
|
|
296
|
+
<AiSelection
|
|
297
|
+
v-model:visible="selectionVisible"
|
|
298
|
+
:exclude-selectors="['.code-block', '.no-selection']"
|
|
299
|
+
/>
|
|
300
|
+
|
|
301
|
+
<div class="code-block">这里选中文字不会弹出操作菜单</div>
|
|
302
|
+
<div class="no-selection">这里也不会弹出</div>
|
|
303
|
+
<p>这里选中文字正常弹出操作菜单</p>
|
|
304
|
+
</template>
|
|
305
|
+
|
|
306
|
+
<script setup lang="ts">
|
|
307
|
+
import { ref } from 'vue';
|
|
308
|
+
import { AiSelection } from '@blueking/chat-x';
|
|
309
|
+
|
|
310
|
+
const selectionVisible = ref(false);
|
|
311
|
+
</script>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## Input / Textarea 支持
|
|
315
|
+
|
|
316
|
+
组件对 `<input>` 和 `<textarea>` 中的选区进行了特殊处理:原生 Range 在这两类元素中无法获取准确坐标,组件会降级使用**输入框自身的 `getBoundingClientRect()`** 作为弹窗位置参考。
|
|
317
|
+
|
|
318
|
+
## 与 ChatBot 联动
|
|
319
|
+
|
|
320
|
+
选中文本后触发快捷指令,自动将选中内容作为上下文发送到聊天窗口:
|
|
321
|
+
|
|
322
|
+
```vue
|
|
323
|
+
<template>
|
|
324
|
+
<div class="page">
|
|
325
|
+
<article>文章内容...</article>
|
|
326
|
+
|
|
327
|
+
<AiSelection
|
|
328
|
+
v-model:visible="selectionVisible"
|
|
329
|
+
:shortcuts="shortcuts"
|
|
330
|
+
@select-shortcut="handleSelectShortcut"
|
|
331
|
+
/>
|
|
332
|
+
|
|
333
|
+
<ChatBot ref="chatBotRef" />
|
|
334
|
+
</div>
|
|
335
|
+
</template>
|
|
336
|
+
|
|
337
|
+
<script setup lang="ts">
|
|
338
|
+
import { ref } from 'vue';
|
|
339
|
+
import { AiSelection, ChatBot, type Shortcut } from '@blueking/chat-x';
|
|
340
|
+
|
|
341
|
+
const selectionVisible = ref(false);
|
|
342
|
+
const chatBotRef = ref();
|
|
343
|
+
|
|
344
|
+
const shortcuts: Shortcut[] = [
|
|
345
|
+
{ id: 'ai-chat', name: '问问小鲸' },
|
|
346
|
+
{ id: 'translate', name: '翻译' },
|
|
347
|
+
{ id: 'explain', name: '解释' },
|
|
348
|
+
];
|
|
349
|
+
|
|
350
|
+
const handleSelectShortcut = (shortcut: Shortcut, selectedText: string) => {
|
|
351
|
+
const prompts: Record<string, string> = {
|
|
352
|
+
translate: `请翻译以下内容:\n${selectedText}`,
|
|
353
|
+
explain: `请解释以下内容:\n${selectedText}`,
|
|
354
|
+
};
|
|
355
|
+
chatBotRef.value?.sendMessage(prompts[shortcut.id] ?? selectedText);
|
|
356
|
+
};
|
|
357
|
+
</script>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
<!-- 全页唯一的 AiSelection 实例,通过各演示区的 mousedown 切换当前配置 -->
|
|
361
|
+
|
|
362
|
+
<AiSelectionComp
|
|
363
|
+
v-model:visible="selectionVisible"
|
|
364
|
+
:shortcuts="currentConfig.shortcuts"
|
|
365
|
+
:max-shortcut-count="currentConfig.maxShortcutCount"
|
|
366
|
+
@select-shortcut="handleSelectShortcut"
|
|
367
|
+
/>
|
|
368
|
+
|
|
369
|
+
## API
|
|
370
|
+
|
|
371
|
+
### Props
|
|
372
|
+
|
|
373
|
+
| 属性名 | 类型 | 默认值 | 必填 | 说明 |
|
|
374
|
+
| ---------------- | ------------ | ------------------- | ---- | ------------------------------------------------------- |
|
|
375
|
+
| visible | `boolean` | - | ✅ | 控制弹窗显示,必须使用 `v-model:visible` |
|
|
376
|
+
| shortcuts | `Shortcut[]` | `DEFAULT_SHORTCUTS` | - | 快捷指令列表,默认为内置「问问小鲸」 |
|
|
377
|
+
| maxShortcutCount | `number` | `3` | - | 直接展示的最大指令数,超出收起到「更多」菜单 |
|
|
378
|
+
| offset | `number` | `10` | - | 弹窗与选区的垂直间距(px) |
|
|
379
|
+
| excludeSelectors | `string[]` | `[]` | - | 排除的 CSS 选择器数组,选区在这些选择器内部时不显示弹窗 |
|
|
380
|
+
|
|
381
|
+
### Events
|
|
382
|
+
|
|
383
|
+
| 事件名 | 参数 | 说明 |
|
|
384
|
+
| --------------- | ------------------------------------ | --------------------------------------- |
|
|
385
|
+
| selectShortcut | `(shortcut: Shortcut, text: string)` | 点击快捷指令时触发,`text` 为选中的文本 |
|
|
386
|
+
| selectionChange | `(text: string)` | 选区文本内容发生变化时触发 |
|
|
387
|
+
|
|
388
|
+
### Slots
|
|
389
|
+
|
|
390
|
+
| 插槽名 | 参数 | 说明 |
|
|
391
|
+
| ------- | --------------------------- | ---------------------------------------------- |
|
|
392
|
+
| default | `{ shortcuts: Shortcut[] }` | 自定义弹窗内容,`shortcuts` 为完整快捷指令列表 |
|
|
393
|
+
|
|
394
|
+
## 定位逻辑
|
|
395
|
+
|
|
396
|
+
| 方向 | 规则 |
|
|
397
|
+
| -------- | ------------------------------------------------------------------------------------ |
|
|
398
|
+
| 水平方向 | 弹窗居中对齐选区,超出视口左/右边界时自动贴边(保留 8px 间距) |
|
|
399
|
+
| 垂直方向 | 优先显示在选区**上方**,上方空间不足时显示在**下方**;两侧均不足时选择空间较大的一侧 |
|
|
400
|
+
|
|
401
|
+
## 默认快捷指令
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
const DEFAULT_SHORTCUTS: Shortcut[] = [{ id: 'ai-chat', name: '问问小鲸' }];
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Shadow DOM 支持
|
|
408
|
+
|
|
409
|
+
组件会递归查找当前 `document.activeElement` 下的 Shadow DOM,兼容 Web Components 场景。若 Shadow DOM 中存在有效文本选区,弹窗同样会正常弹出并定位。
|
|
410
|
+
|
|
411
|
+
## 类型定义
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
import { type Component, type VNode, h } from 'vue';
|
|
415
|
+
|
|
416
|
+
interface Shortcut {
|
|
417
|
+
id: string;
|
|
418
|
+
name: string;
|
|
419
|
+
key?: string;
|
|
420
|
+
icon?: ((c: typeof h) => Component | VNode) | string | VNode;
|
|
421
|
+
components?: ShortcutComponent[];
|
|
422
|
+
// ... 其余字段参见 ShortcutRender 文档
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
## 使用场景
|
|
427
|
+
|
|
428
|
+
- **文章阅读划词**:选中内容后弹出「问问小鲸」「翻译」「解释」等快捷入口
|
|
429
|
+
- **代码解释**:在代码区块中选中代码片段,触发「解释代码」「优化建议」等操作
|
|
430
|
+
- **文本处理**:对选中内容进行翻译、总结、改写等 AI 增强处理
|
|
431
|
+
- **与 ChatBot 联动**:选中文本后将内容作为上下文自动填入聊天输入框
|
|
432
|
+
|
|
433
|
+
## 关联组件
|
|
434
|
+
|
|
435
|
+
- [ShortcutBtn](../atomic/shortcut-btn.md) — 弹窗内快捷指令按钮单元
|
|
436
|
+
- [ChatInput](./chat-input.md) — 选区文本常回填到聊天输入框
|