@blueking/chat-x 0.0.50 → 0.0.51-beta.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/dist/ag-ui/types/contents.d.ts +2 -0
- package/dist/ag-ui/types/messages.d.ts +5 -0
- package/dist/common/constants.d.ts +1 -1
- package/dist/components/ai-buttons/file-upload-btn/file-upload-btn.vue.d.ts +0 -2
- package/dist/components/chat-content/file-content/file-content.vue.d.ts +5 -2
- package/dist/components/chat-content/file-content/upload-file-item.vue.d.ts +12 -0
- package/dist/components/chat-content/file-content/upload-image-item.vue.d.ts +21 -0
- package/dist/components/chat-input/ai-slash-editor/ai-slash-editor.vue.d.ts +1 -1
- package/dist/components/chat-input/build-default-placeholder.d.ts +7 -0
- package/dist/components/chat-input/chat-input.vue.d.ts +1 -1
- package/dist/components/chat-message/message-container/message-container.vue.d.ts +1 -0
- package/dist/components/chat-message/message-render/message-render.vue.d.ts +2 -0
- package/dist/components/chat-message/user-message/user-message.vue.d.ts +3 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/message-tools/message-time/format-message-time.d.ts +8 -0
- package/dist/components/message-tools/message-time/message-time.vue.d.ts +8 -0
- package/dist/components/message-tools/message-tools.vue.d.ts +11 -1
- package/dist/composables/use-custom-tab.d.ts +5 -3
- package/dist/composables/use-global-config.d.ts +3 -0
- package/dist/composables/use-message-group.d.ts +150 -72
- package/dist/icons/execution.d.ts +6 -0
- package/dist/icons/tools.d.ts +3 -0
- package/dist/index.css +1 -1
- package/dist/index.js +3124 -2837
- package/dist/index.js.map +1 -1
- package/dist/lang/lang.d.ts +8 -7
- package/dist/mcp/generated/docs/ai-slash-input.md +2 -0
- package/dist/mcp/generated/docs/assistant-message.md +9 -7
- package/dist/mcp/generated/docs/chat-container.md +38 -32
- package/dist/mcp/generated/docs/chat-input.md +18 -12
- package/dist/mcp/generated/docs/cite-content.md +3 -3
- package/dist/mcp/generated/docs/desc-panel.md +32 -10
- package/dist/mcp/generated/docs/execution-summary.md +3 -3
- package/dist/mcp/generated/docs/file-artifact-panel.md +6 -4
- package/dist/mcp/generated/docs/file-content.md +89 -73
- package/dist/mcp/generated/docs/file-upload-btn.md +16 -18
- package/dist/mcp/generated/docs/message-container.md +3 -0
- package/dist/mcp/generated/docs/message-render.md +2 -1
- package/dist/mcp/generated/docs/message-time.md +180 -0
- package/dist/mcp/generated/docs/message-tools.md +47 -12
- package/dist/mcp/generated/docs/messages.md +9 -0
- package/dist/mcp/generated/docs/toolcall-render.md +82 -43
- package/dist/mcp/generated/docs/use-artifact-preview.md +19 -17
- package/dist/mcp/generated/docs/use-custom-tab.md +12 -8
- package/dist/mcp/generated/docs/use-global-config.md +15 -5
- package/dist/mcp/generated/docs/user-message.md +9 -0
- package/dist/mcp/generated/docs/user-question-card.md +2 -0
- package/dist/mcp/generated/index.json +46 -6
- package/dist/types/input.d.ts +6 -0
- package/dist/utils/file.d.ts +7 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/merge-tools-by-id.d.ts +6 -0
- package/dist/utils/upload-file.d.ts +35 -0
- package/package.json +1 -1
package/dist/lang/lang.d.ts
CHANGED
|
@@ -14,10 +14,10 @@ export declare const lang: {
|
|
|
14
14
|
readonly 取消: "Cancel";
|
|
15
15
|
readonly 预览内容: "Preview Content";
|
|
16
16
|
readonly 跳转详情: "Jump to Detail";
|
|
17
|
-
readonly
|
|
18
|
-
readonly
|
|
19
|
-
readonly
|
|
20
|
-
readonly
|
|
17
|
+
readonly 调用工具: "Call Tool";
|
|
18
|
+
readonly '\u8BFB\u53D6 Skill': "Read Skill";
|
|
19
|
+
readonly 正在调用: "Calling";
|
|
20
|
+
readonly 正在读取: "Reading";
|
|
21
21
|
readonly 说出您的想法: "Tell us your thoughts";
|
|
22
22
|
readonly '\u4EC0\u4E48\u539F\u56E0\u8BA9\u4F60\u6EE1\u610F\uFF1F': "What makes you satisfied?";
|
|
23
23
|
readonly '\u4EC0\u4E48\u539F\u56E0\u8BA9\u4F60\u4E0D\u6EE1\u610F\uFF1F': "What makes you dissatisfied?";
|
|
@@ -37,6 +37,7 @@ export declare const lang: {
|
|
|
37
37
|
readonly 停止生成: "Stop generating";
|
|
38
38
|
readonly 正在停止: "Stopping";
|
|
39
39
|
readonly 耗时: "Duration";
|
|
40
|
+
readonly 昨天: "Yesterday";
|
|
40
41
|
readonly 参数: "Parameters";
|
|
41
42
|
readonly 描述: "Description";
|
|
42
43
|
readonly 执行情况: "Execution Status";
|
|
@@ -73,7 +74,7 @@ export declare const lang: {
|
|
|
73
74
|
readonly 结构化输出: "Structured Output";
|
|
74
75
|
readonly 手动跳过: "Manual Skip";
|
|
75
76
|
readonly 暂无数据: "No Data";
|
|
76
|
-
readonly '\u8C03\u7528 MCP
|
|
77
|
+
readonly '\u8C03\u7528 MCP': "Call MCP";
|
|
77
78
|
readonly 更多: "More";
|
|
78
79
|
readonly 算法方案评审单: "Algorithm Plan Review Ticket";
|
|
79
80
|
readonly 评审中: "Reviewing";
|
|
@@ -128,7 +129,7 @@ export declare const lang: {
|
|
|
128
129
|
readonly 在对话中定位: "Locate in Chat";
|
|
129
130
|
readonly 全选: "Select All";
|
|
130
131
|
readonly 确定: "Confirm";
|
|
131
|
-
readonly '\u4E0A\u4F20\
|
|
132
|
+
readonly '\u4E0A\u4F20\u6587\u4EF6\uFF0C\u6700\u591A\u652F\u6301 {count} \u4E2A\uFF0C\u5355\u4E2A\u6700\u5927 {size}MB': "Upload file, up to {count} files, max {size}MB each";
|
|
132
133
|
readonly '\u4F60\u597D\uFF0C\u6211\u662F\u5C0F\u9CB8': "Hello, I am BlueKing AI Bot";
|
|
133
134
|
readonly 清空搜索: "Clear Search";
|
|
134
135
|
readonly 搜索结果为空: "Search Result is Empty";
|
|
@@ -156,4 +157,4 @@ export declare const lang: {
|
|
|
156
157
|
readonly 预览加载失败: "Failed to load preview";
|
|
157
158
|
readonly 暂无可预览的文件: "No file to preview";
|
|
158
159
|
};
|
|
159
|
-
export declare const t: (key: keyof typeof lang) => "Send" | "Stop" | "Ask AI" | "Copy" | "Share" | "Like" | "Unsatisfied" | "Delete" | "Quote" | "Regenerate" | "Regenerating will clear the content below" | "Submit" | "Cancel" | "Preview Content" | "Jump to Detail" | "Call Tool
|
|
160
|
+
export declare const t: (key: keyof typeof lang) => "Send" | "Stop" | "Ask AI" | "Copy" | "Share" | "Like" | "Unsatisfied" | "Delete" | "Quote" | "Regenerate" | "Regenerating will clear the content below" | "Submit" | "Cancel" | "Preview Content" | "Jump to Detail" | "Call Tool" | "Read Skill" | "Calling" | "Reading" | "Tell us your thoughts" | "What makes you satisfied?" | "What makes you dissatisfied?" | "Return Content" | "Edit" | "Deep Thinking" | "Quick Thinking" | "Image to Text" | "Loading image..." | "Failed to load image" | "Thinking..." | "Thinking Completed" | "Thinking Failed" | "Copy Success" | "Copy Failed" | "Return to bottom" | "Stop generating" | "Stopping" | "Duration" | "Yesterday" | "Parameters" | "Description" | "Execution Status" | "Running" | "Success" | "Failed" | "Pending" | "To Be Executed" | "Details" | "Retry" | "Retrying" | "Skipping" | "The task is retrying and cannot be skipped" | "The task is skipping and cannot be retried" | "Node" | "Node Config" | "Node Output" | "Basic Info" | "Flow Template" | "Node Name" | "Step Name" | "Execution Plan" | "Optional" | "Failure Handler" | "Timeout Control" | "Yes" | "No" | "Input Params" | "Output Params" | "Param Name" | "Param Value" | "Name" | "Structured Output" | "Manual Skip" | "No Data" | "Call MCP" | "More" | "Algorithm Plan Review Ticket" | "Reviewing" | "Approving" | "Abandoned" | "Approved" | "Cancelled" | "Expired" | "Rejected" | "Revoked" | "Ticket No." | "Submitted At" | "Current Handler" | "None" | "View Ticket Detail" | "Copy Ticket" | "Copy Ticket Link" | "Cancel Approval" | "Approval Cancelled" | "Refresh Ticket Status" | "This ticket has been rejected and cannot be cancelled" | "This ticket has been approved and cannot be cancelled" | "This ticket has been cancelled, no need to click again" | "Approval cannot be cancelled in the current status" | "There are {count} pending approval tickets in the current conversation. To continue, cancel approval first." | "Unsupported interrupt message" | "Searching" | "Search Completed" | "Upload File" | "Select model" | "Search models" | "Requesting..." | "Cancel satisfied" | "Cancel dissatisfied" | "Confirm delete this answer?" | "This operation cannot be undone. Please proceed with caution!" | "Preview" | "Zoom Out" | "Zoom In" | "Rotate" | "Download" | "Sorry, image loading failed. Please try reloading." | "Reset" | "Reload" | "W" | "H" | "Upload Image" | "Search keyword" | "Select date" | "Locate in Chat" | "Select All" | "Confirm" | "Upload file, up to {count} files, max {size}MB each" | "Hello, I am BlueKing AI Bot" | "Clear Search" | "Search Result is Empty" | "Valid Evidence" | "Full Screen" | "Exit Full Screen" | "Please choose to continue" | "Continue" | "Received: " | "Done" | "Skip" | "Single" | "Multiple" | "Others" | "Completed" | "question(s)" | "Answers" | "Replied" | "Please enter..." | "File Artifacts" | "File List" | "Search file keyword" | "Failed to load preview" | "No file to preview" | "发送" | "停止" | "问问小鲸" | "复制" | "分享" | "点赞" | "不满意" | "删除" | "引用" | "重新生成" | "重新生成将清空下文内容" | "提交" | "取消" | "预览内容" | "跳转详情" | "调用工具" | "读取 Skill" | "正在调用" | "正在读取" | "说出您的想法" | "什么原因让你满意?" | "什么原因让你不满意?" | "返回内容" | "编辑" | "深度思考" | "快速思考" | "图生文" | "图片加载中..." | "图片加载失败" | "思考中" | "已思考完成" | "思考失败" | "复制成功" | "复制失败" | "返回底部" | "停止生成" | "正在停止" | "耗时" | "昨天" | "参数" | "描述" | "执行情况" | "执行中" | "成功" | "失败" | "挂起" | "待执行" | "详情" | "重试" | "重试中" | "跳过中" | "任务正在重试中,不可跳过" | "任务正在跳过中,不可重试" | "节点" | "节点配置" | "节点输出" | "基础信息" | "流程模板" | "节点名称" | "步骤名称" | "执行方案" | "是否可选" | "失败处理" | "超时控制" | "是" | "否" | "输入参数" | "输出参数" | "参数名" | "参数值" | "名称" | "变量说明" | "结构化输出" | "手动跳过" | "暂无数据" | "调用 MCP" | "更多" | "算法方案评审单" | "评审中" | "审批中" | "已废弃" | "已批准" | "已通过" | "已取消" | "已过期" | "已拒绝" | "已撤销" | "单据编号" | "提交时间" | "当前处理人" | "无" | "查看单据详情" | "复制单据" | "复制单据链接" | "取消审批" | "已取消审批" | "刷新单据状态" | "单据已取消审批" | "该单据已被拒绝,无法取消" | "该单据已通过,无法取消" | "单据已取消,无需重复点击" | "当前状态无法取消审批" | "当前会话有 {count} 个待审批单,如需继续,请先取消审批" | "暂不支持的中断消息" | "检索中" | "检索完成" | "上传文件" | "选择模型" | "搜索模型关键字" | "请求中..." | "取消满意" | "取消不满意" | "确认删除该回答?" | "删除操作无法撤回,请谨慎操作!" | "预览" | "缩小" | "放大" | "旋转" | "下载" | "抱歉,图片加载失败,可尝试重新加载" | "重置" | "重新加载" | "宽" | "高" | "上传图片" | "搜索 关键字" | "选择日期" | "在对话中定位" | "全选" | "确定" | "上传文件,最多支持 {count} 个,单个最大 {size}MB" | "你好,我是小鲸" | "清空搜索" | "搜索结果为空" | "有效证据" | "全屏" | "退出全屏" | "请选择以继续" | "继续" | "收到信息:" | "待审批" | "已审批" | "完成" | "跳过" | "单选" | "多选" | "其他" | "已完成" | "题" | "回答内容" | "已回复" | "请输入..." | "文件产物" | "文件列表" | "搜索文件关键字" | "预览加载失败" | "暂无可预览的文件";
|
|
@@ -30,13 +30,14 @@ AI 助手消息展示组件:正文(Markdown)、工具调用(Tool Calls
|
|
|
30
30
|
AssistantMessage(根类名:ai-assistant-message)
|
|
31
31
|
├── ai-assistant-message-content(内容区,v-if content)
|
|
32
32
|
│ └── [default slot { content }] 或 ContentRender → MarkdownContent
|
|
33
|
-
├──
|
|
33
|
+
├── ai-assistant-message-toolcalls(v-if toolCalls 非空,flex column,gap: 8px)
|
|
34
|
+
│ └── ToolCallRender × N(toolCalls,不受 slot 影响)
|
|
34
35
|
└── MessageArtifacts(v-if property.artifacts 非空)
|
|
35
36
|
└── ArtifactFileCard × N(点击 → useArtifactPreview → 侧栏 FileArtifactPanel → ArtifactPreviewHost)
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
- **内容区**:`content` 经 `ContentRender`(`MessageContentType.Text`)由 `MarkdownContent` 渲染;default slot 仅收到 `{ content }`
|
|
39
|
-
- **工具调用区**:每个 `toolCall` 渲染一个 `ToolCallRender
|
|
40
|
+
- **工具调用区**:每个 `toolCall` 渲染一个 `ToolCallRender`,位于内容区下方;多条工具调用由 `.ai-assistant-message-toolcalls` 容器统一控制为 `8px` 间距,不受消息根节点 `12px` 间距影响
|
|
40
41
|
- **文件产物区**:读取 `property.artifacts`,用 `uid ?? String(id)` 作为 `messageUid` 传给 `MessageArtifacts`
|
|
41
42
|
|
|
42
43
|
## 基础用法
|
|
@@ -198,7 +199,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
198
199
|
|
|
199
200
|
### MCP 工具调用
|
|
200
201
|
|
|
201
|
-
`function.
|
|
202
|
+
`function.type` 为 `'mcp'`(或旧数据仅有 `mcpName`)时,`ToolCallRender` 头部显示为「调用 MCP {mcpName} / {name}」:
|
|
202
203
|
|
|
203
204
|
```vue
|
|
204
205
|
<script setup lang="ts">
|
|
@@ -207,6 +208,7 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
207
208
|
id: 'call_mcp_1',
|
|
208
209
|
type: 'function',
|
|
209
210
|
function: {
|
|
211
|
+
type: 'mcp', // 调用类型,缺省时有 mcpName 也会兼容判定为 MCP
|
|
210
212
|
name: 'query_database',
|
|
211
213
|
arguments: '{"sql": "SELECT * FROM users LIMIT 10"}',
|
|
212
214
|
description: '执行数据库查询',
|
|
@@ -282,13 +284,13 @@ AI 可在一次回复中发起多个工具调用,组件依次渲染:
|
|
|
282
284
|
|
|
283
285
|
传给每个 `ToolCallRender` 的 `status` 按以下优先级计算:
|
|
284
286
|
|
|
285
|
-
1. 无 `toolMessage` → `MessageStatus.Pending
|
|
286
|
-
2. `toolMessage.error` 为真 → `MessageStatus.Error
|
|
287
|
+
1. 无 `toolMessage` → `MessageStatus.Pending`(进行中)
|
|
288
|
+
2. `toolMessage.error` 为真 → `MessageStatus.Error`(失败)
|
|
287
289
|
3. 否则 → `toolMessage.status ??` 本组件 `status`
|
|
288
290
|
|
|
289
|
-
|
|
291
|
+
**进行中**(有 `toolCalls`、尚无 `toolMessage`;即便助手 `status` 已是 `complete`,工具调用仍显示「正在调用」):
|
|
290
292
|
|
|
291
|
-
|
|
293
|
+
**成功**(`toolMessage.status = "complete"`):
|
|
292
294
|
|
|
293
295
|
## 自定义内容渲染
|
|
294
296
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- AI SUMMARY -->
|
|
2
2
|
## 快速了解
|
|
3
3
|
|
|
4
|
-
完整对话容器,组合消息列表、输入区、模型选择、快捷指令、执行摘要、分享选择和自定义 Tab。 透传 models / selectedModel;支持 welcomeTitle 与 #welcome。 源码位置:src/components/chat-container/chat-container.vue。
|
|
4
|
+
完整对话容器,组合消息列表、输入区、模型选择、快捷指令、执行摘要、分享选择和自定义 Tab。 透传 models / selectedModel;支持 welcomeTitle 与 #welcome。 侧栏展开/折叠由外部 v-model:asideCollapsed 严格受控(传入后以外部值为准,内部展开动作仅发 update 事件),不再依赖执行数据或文件产物有无;无数据时侧栏照常展开并展示空态。 侧栏固定从右侧展开(无 placement prop),且不再内置折叠按钮。 「文件产物」Tab 常驻挂载。 源码位置:src/components/chat-container/chat-container.vue。
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **message-container** — 消息列表与滚动区域
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
|
|
23
23
|
## 核心能力
|
|
24
24
|
|
|
25
|
-
- **分栏布局**:基于 `ResizeLayout
|
|
25
|
+
- **分栏布局**:基于 `ResizeLayout`,侧栏固定从右侧展开且无内置折叠按钮;展开 / 折叠由外部通过 `v-model:asideCollapsed` 判断,容器只负责渲染与回写,不再依赖 `executionGroups`、`keyword` 等数据条件。无数据时侧栏照常展开,由各面板展示空态
|
|
26
|
+
- **顶部分割线**:容器自身不再绘制 `border-top`。侧栏展开时的顶栏分割线由业务 Header(如 AI 小鲸 `ai-header`)在 `asideCollapsed === false` 时绘制,以保证贯穿全宽
|
|
26
27
|
- **消息分组**:内置 `useMessageGroup`,自动分组、Tool 合并、Loading 注入
|
|
27
28
|
- **输入区状态推导**:对内 `messageStatus` 取 `inputStatus`——分组中存在 `LOADING_MESSAGE_ID`(`'__loading__'`)时用 `MessageStatus.Fetching`,否则用外部 `messageStatus`,保证「已发未流式」阶段也能停止、并避免重复发送
|
|
28
29
|
- **待审批发送阻塞**:存在 `AIDevToolApproval` 且为 `pending` / `draft` 时,输入区上方提示,并通过 `ChatInput.sendDisabledTip` 禁止发送
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
- **模型选择**:透传 `models`、`v-model:selectedModel` 与 `@modelChange` 至 `ChatInput`,传入 `models` 后在发送按钮左侧展示 [ModelSelector](/components/input/model-selector)
|
|
32
33
|
- **分享模式 / 渲染模式**:内置多选分享;`renderMode` 经 Provider 下传。`Share` 态开放侧栏只读查看,隐藏底部输入与「重试 / 跳过」等交互
|
|
33
34
|
- **字号主题**:`size` 为 `small`(默认 12px)/ `normal`(14px);根节点 `data-ai-size`,浮层同步 `document.body.dataset.aiSize`
|
|
35
|
+
- **消息时间时区**:`timezone` 经 `useGlobalConfig` 下传给 `MessageTime`,统一整个会话的时间展示时区;未配置时按浏览器时区
|
|
34
36
|
- **空状态欢迎页**:无消息时展示 Banner、`welcomeTitle`(默认「你好,我是小鲸」)与 `openingRemark`
|
|
35
37
|
|
|
36
38
|
## 组件结构
|
|
@@ -39,15 +41,14 @@
|
|
|
39
41
|
ai-chat-container(:data-ai-size="size")
|
|
40
42
|
├── Loading(chatLoading 时)
|
|
41
43
|
└── ResizeLayout
|
|
42
|
-
├── aside
|
|
43
|
-
│
|
|
44
|
+
├── aside(侧边栏,固定右侧)
|
|
45
|
+
│ └── .ai-full-screen-wrapper(全屏目标容器,ref=fullScreenRef)
|
|
44
46
|
│ │ ├── Tab 标签页
|
|
45
47
|
│ │ │ ├── 执行情况(默认 Tab)
|
|
46
48
|
│ │ │ ├── 自定义 Tab × N(可关闭;标签可由 getSideTabRenderComponent 自定义)
|
|
47
49
|
│ │ │ └── #setting → 全屏/退出全屏 ToolBtn
|
|
48
50
|
│ │ ├── ExecutionSummary(执行情况 Tab 内容)
|
|
49
51
|
│ │ └── 自定义 Tab 组件(getSideRenderComponent 优先,否则 data.component;可注入 #locateButton)
|
|
50
|
-
│ └── collapse-button(CollapsedIcon)
|
|
51
52
|
└── main(主内容区)
|
|
52
53
|
├── MessageContainer(有消息时;#group / #message 可自定义)
|
|
53
54
|
├── 欢迎页(无消息时 .ai-welcome-content)
|
|
@@ -131,19 +132,23 @@ ai-chat-container(:data-ai-size="size")
|
|
|
131
132
|
|
|
132
133
|
## 侧边栏与执行摘要
|
|
133
134
|
|
|
134
|
-
侧边栏默认包含「执行情况」Tab,展示所有工具调用和 FlowAgent 类型的 Activity 消息。支持关键词搜索过滤和点击定位到对话中的消息位置。
|
|
135
|
+
侧边栏默认包含「执行情况」Tab,展示所有工具调用和 FlowAgent 类型的 Activity 消息。支持关键词搜索过滤和点击定位到对话中的消息位置。Tab 标签内 `.ai-execution-summary-icon` 固定 16×16px,避免被 flex 压缩。
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
**展示条件**:侧栏是否渲染只取决于折叠态与是否存在可见 Tab —— `asideCollapsed === false` 且 `displayTabs` 非空即展开,与 `executionGroups`、`keyword`、是否有文件产物均无关。无执行数据时 `ExecutionSummary` 展示自身空态,无文件产物时 `FileArtifactPanel` 展示整块空态。`renderMode === Share` 分享态同样按折叠态展示侧栏(开放只读查看流程智能体详情/证据/执行情况),仅底部输入区保持隐藏。
|
|
137
138
|
|
|
138
|
-
|
|
139
|
+
**展开 / 折叠由外部判断(严格受控)**:只要传入了 `asideCollapsed`,折叠态就**一律以外部值为准**。容器内部的展开动作(点击文件卡片预览、`addCustomTab` 打开节点详情等)只发出 `update:asideCollapsed` 请求,外部不改值就不会展开 —— 所以务必用 `v-model:asideCollapsed` 绑定,只写 `:aside-collapsed` 会让这些内部入口失效。完全不传该 prop 时退化为组件内部状态(默认折叠),内部入口照常生效。容器不会因为数据变空而自动收起或重置自定义 Tab。
|
|
139
140
|
|
|
140
141
|
```vue
|
|
141
142
|
<template>
|
|
143
|
+
<!-- 业务方自行提供展开/收起入口;可复用包内 CollapsedAsideIcon -->
|
|
144
|
+
<button @click="asideCollapsed = !asideCollapsed">
|
|
145
|
+
{{ asideCollapsed ? '展开侧栏' : '收起侧栏' }}
|
|
146
|
+
</button>
|
|
142
147
|
<ChatContainer
|
|
143
148
|
v-model="inputValue"
|
|
149
|
+
v-model:aside-collapsed="asideCollapsed"
|
|
144
150
|
:messages="messages"
|
|
145
151
|
:message-status="messageStatus"
|
|
146
|
-
placement="left"
|
|
147
152
|
:on-send-message="handleSendMessage"
|
|
148
153
|
:on-agent-action="handleAgentAction"
|
|
149
154
|
@stop-streaming="handleStopStreaming"
|
|
@@ -152,6 +157,11 @@ ai-chat-container(:data-ai-size="size")
|
|
|
152
157
|
</template>
|
|
153
158
|
|
|
154
159
|
<script setup lang="ts">
|
|
160
|
+
import { shallowRef } from 'vue';
|
|
161
|
+
// import { CollapsedAsideIcon } from '@blueking/chat-x';
|
|
162
|
+
|
|
163
|
+
const asideCollapsed = shallowRef(true);
|
|
164
|
+
|
|
155
165
|
const handleCollapseChange = (isCollapse: boolean, resizeAsideWidth: number) => {
|
|
156
166
|
console.log('侧边栏折叠:', isCollapse, '宽度:', resizeAsideWidth);
|
|
157
167
|
};
|
|
@@ -160,16 +170,9 @@ ai-chat-container(:data-ai-size="size")
|
|
|
160
170
|
|
|
161
171
|
**渲染效果**(包含工具调用消息时,侧边栏自动展示「执行情况」)
|
|
162
172
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
| `placement` | 侧边栏位置 | 折叠按钮位置 | 折叠图标旋转 |
|
|
166
|
-
| ----------- | ------------ | ------------ | ------------ |
|
|
167
|
-
| `left` | 左侧(默认) | 主区域左边缘 | 折叠时旋转 180° |
|
|
168
|
-
| `right` | 右侧 | 主区域右边缘 | 默认旋转 180°,折叠时恢复 0° |
|
|
169
|
-
|
|
170
|
-
> 折叠按钮仅展示 `CollapsedIcon`(不再显示「执行情况」文案),通过图标旋转方向指示展开/折叠状态。
|
|
173
|
+
侧边栏固定从**右侧**展开(内部 `ResizeLayout` 的 `placement` 恒为 `right`),不再支持左侧布局,也不再内置折叠按钮 —— 展开 / 收起入口由业务方自行提供,通过 `v-model:asideCollapsed` 驱动。
|
|
171
174
|
|
|
172
|
-
|
|
175
|
+
**展开 / 收起动画**:侧栏宽度做 `0.3s cubic-bezier(0.4, 0, 0.2, 1)` 过渡,内容同步淡入淡出;动画期间内容锁定展开态宽度(CSS 变量 `--resize-aside-width`)由外层裁切,避免被压缩重排。拖拽调宽时过渡自动关闭,保证跟手。
|
|
173
176
|
|
|
174
177
|
## 侧栏全屏
|
|
175
178
|
|
|
@@ -183,7 +186,7 @@ ai-chat-container(:data-ai-size="size")
|
|
|
183
186
|
|
|
184
187
|
## 自定义 Tab
|
|
185
188
|
|
|
186
|
-
通过 `ref` 获取组件实例后,使用 `addCustomTab` / `removeCustomTab` 动态管理侧边栏 Tab
|
|
189
|
+
通过 `ref` 获取组件实例后,使用 `addCustomTab` / `removeCustomTab` 动态管理侧边栏 Tab。自定义 Tab 的生命周期由调用方掌控,容器不会因执行数据变空而自动清理(仅组件卸载时 `resetCustomTab`)。
|
|
187
190
|
|
|
188
191
|
### Tab 排序与显隐
|
|
189
192
|
|
|
@@ -241,14 +244,15 @@ ai-chat-container(:data-ai-size="size")
|
|
|
241
244
|
|
|
242
245
|
### 内置「文件产物」Tab
|
|
243
246
|
|
|
244
|
-
|
|
247
|
+
除「执行情况」外,容器内置一个常驻固定 Tab —— **「文件产物」**(`name: 'file-artifact'`),用于聚合预览当前会话所有 `AssistantMessage.property.artifacts`(按 `outputId` 去重):
|
|
245
248
|
|
|
246
|
-
-
|
|
249
|
+
- **常驻挂载 / 默认选中**:容器初始化即通过 `ensureCustomTab` 挂上该 Tab(不展开侧栏);因 `order: -1` 排在 Tab 栏首位,在用户未主动切换过 Tab 时它就是侧栏的默认面板。不随产物有无增删,无产物时由面板展示整块空态
|
|
250
|
+
- **默认图标**:`ArtifactTabIcon`,16×16 线性折角文档,`fill` 走 `currentColor` 以继承 Tab 选中/默认色
|
|
247
251
|
- **主动打开**:点击 AI 回复中的文件卡片([ArtifactFileCard](/components/message/assistant-message))时,容器通过 `useArtifactPreviewProvider` 以 `outputId` 命中该文件,再 `addCustomTab` 展开侧栏并选中「文件产物」
|
|
248
252
|
- **排序 / 关闭**:`order: -1` 排在「执行情况」之前,`closable: false` 不可关闭
|
|
249
|
-
-
|
|
250
|
-
- **内容**:由 [FileArtifactPanel](/components/message/file-artifact-panel)
|
|
251
|
-
-
|
|
253
|
+
- **命中态维护**:产物列表为空时清空命中;命中项已不在列表时回落到第一个 `outputId`
|
|
254
|
+
- **内容**:由 [FileArtifactPanel](/components/message/file-artifact-panel) 渲染列表与下载头(无产物时为整块空态),预览委托内部 `ArtifactPreviewHost`;`download_url` / `preview_url` 通过 `onArtifactClick` 异步获取。文本类(`html` / `markdown` / `md` / `txt` / `json`)拉 `download_url` 正文直渲染(`md` 与 `markdown` 等价);其余类型用 `preview_url` iframe(一般为后台转好的 PDF)
|
|
255
|
+
- **状态管理**:命中、切换与 URL 缓存由 [useArtifactPreview](/composables/use-artifact-preview) 提供(Provider 在容器内、Consumer 在文件卡片 / 面板内);正文加载与分类型渲染由 Host 内部完成
|
|
252
256
|
- **未传 `onArtifactClick`**:下载按钮隐藏,预览区展示无数据
|
|
253
257
|
|
|
254
258
|
详见 [FileArtifactPanel 文件产物预览](/components/message/file-artifact-panel) 与 [useArtifactPreview 文件产物预览](/composables/use-artifact-preview)。
|
|
@@ -573,7 +577,7 @@ ai-chat-container(:data-ai-size="size")
|
|
|
573
577
|
|
|
574
578
|
### 自定义按钮触发多选(triggerSelection)
|
|
575
579
|
|
|
576
|
-
除内置「分享」外,任意自定义工具按钮标记 `triggerSelection: true` 后,点击即可复用同一套多选流程(勾选消息 → `SelectionFooter` 确认),确认时同样触发 `confirmShare`。配合 `messageTools` / `updateTools`(合并规则见 [MessageContainer · 自定义消息工具栏](/components/setup/message-container)
|
|
580
|
+
除内置「分享」外,任意自定义工具按钮标记 `triggerSelection: true` 后,点击即可复用同一套多选流程(勾选消息 → `SelectionFooter` 确认),确认时同样触发 `confirmShare`。配合 `messageTools` / `updateTools` / `userMessageTools`(合并规则见 [MessageContainer · 自定义消息工具栏](/components/setup/message-container))即可扩展如「保存」「收藏到空间」等批量操作,或隐藏用户消息上的编辑 / 删除。
|
|
577
581
|
|
|
578
582
|
```vue
|
|
579
583
|
<template>
|
|
@@ -705,14 +709,14 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
|
|
|
705
709
|
| getSideTabRenderComponent | `(h, tab, { removeCustomTab }) => VNode \| undefined` | — | 自定义侧栏 Tab 标签渲染;未返回时使用默认图标 + 文案 + 关闭按钮 |
|
|
706
710
|
| models | `IModelOption[]` | — | 可选模型列表(继承自 ChatInput);传入后在发送按钮左侧展示 ModelSelector |
|
|
707
711
|
| openingRemark | `string` | — | 开场白,无消息时显示,支持 Markdown |
|
|
708
|
-
|
|
|
709
|
-
| resizeProps | `{ disabled?: boolean; initialDivide?: number \| string; max?: number; min?: number }` | — | 透传给内部 `ResizeLayout`;与默认 `collapsible: false`、`immediate: true`、`min: 400` 合并;`placement` 始终取自本组件。**数字型** `initialDivide` 还会作为内部侧栏宽度初值(驱动 `--resize-main-width`,并在展开时作为 `collapseChange` 的 `width`);百分比等字符串则回退为 `400` |
|
|
712
|
+
| resizeProps | `{ disabled?: boolean; initialDivide?: number \| string; max?: number; min?: number }` | — | 透传给内部 `ResizeLayout`;与默认 `collapsible: false`、`immediate: true`、`min: 400` 合并;`placement` 固定为 `right`,不可覆盖。**数字型** `initialDivide` 还会作为内部侧栏宽度初值(驱动 `--resize-main-width`,并在展开时作为 `collapseChange` 的 `width`);百分比等字符串则回退为 `400` |
|
|
710
713
|
| size | `'normal' \| 'small'` | `'small'` | 字号主题:`small` 12px / `normal` 14px;根节点设置 `data-ai-size` 并注入 `useGlobalConfig` |
|
|
714
|
+
| timezone | `string` | — | 消息时间展示所用的 IANA 时区名(如 `Asia/Shanghai`);经 `useGlobalConfig` 注入,未配置时按浏览器时区展示,详见 [MessageTime](/components/feedback/message-time) |
|
|
711
715
|
| welcomeTitle | `string` | — | 欢迎页标题;未传时默认展示「你好,我是小鲸」 |
|
|
712
716
|
| onCustomTabChange | `(tab: CustomTab) => Promise<any>` | — | 自定义 Tab 切换回调,返回值作为 Tab 组件 props |
|
|
713
717
|
| onArtifactClick | `(file: AIFileInfo) => Promise<{ download_url?: string; preview_url?: string }>` | — | 异步获取下载 / 预览链接(每次调用重新获取,无缓存;同文件并发去重)。文本类预览依赖 `download_url`,iframe 类依赖 `preview_url`;未传则隐藏下载、预览无数据 |
|
|
714
718
|
|
|
715
|
-
> 其余 Props(如 `messages`、`messageStatus`、`onSendMessage`、`shortcuts` 等)继承自 [ChatInput](/components/input/chat-input) 与 [MessageContainer](/components/setup/message-container)
|
|
719
|
+
> 其余 Props(如 `messages`、`messageStatus`、`onSendMessage`、`shortcuts`、`userMessageTools` 等)继承自 [ChatInput](/components/input/chat-input) 与 [MessageContainer](/components/setup/message-container)。`userMessageTools` 透传给内部 `MessageContainer`,用于按 id 覆盖或隐藏用户消息工具栏。
|
|
716
720
|
|
|
717
721
|
### v-model
|
|
718
722
|
|
|
@@ -723,6 +727,7 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
|
|
|
723
727
|
| cite | `string` | 引用内容 |
|
|
724
728
|
| renderMode | `RenderMode` | 渲染模式(默认 `Chat`)。`Share` 开放侧栏只读查看并隐藏底部输入与交互操作;`Test` 隐藏分享按钮 |
|
|
725
729
|
| selectedModel | `string` | 当前选中模型的 `llm_name`,透传至 ChatInput 的 ModelSelector |
|
|
730
|
+
| asideCollapsed | `boolean` | 侧栏折叠态,**严格受控**:传入后一律以外部值为准,内部展开动作(文件预览、`addCustomTab`)只发 `update:asideCollapsed`,外部不改则不展开;不传时由组件内部自持(默认折叠) |
|
|
726
731
|
|
|
727
732
|
### Events
|
|
728
733
|
|
|
@@ -732,7 +737,8 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
|
|
|
732
737
|
| shortcutClose | — | 关闭快捷指令表单 |
|
|
733
738
|
| shortcutSubmit | `(formModel: Record<string, unknown>)` | 提交快捷指令表单 |
|
|
734
739
|
| confirmShare | `(messages: Message[], source?: IToolBtn)` | 确认分享/多选,携带选中的消息与触发按钮对象(`source`,用于区分 share/save 等场景) |
|
|
735
|
-
| collapseChange | `(isCollapse: boolean, width: number)` |
|
|
740
|
+
| collapseChange | `(isCollapse: boolean, width: number)` | 侧边栏折叠/展开状态变化(含宽度,便于外层容器扩宽) |
|
|
741
|
+
| update:asideCollapsed | `(collapsed: boolean)` | 折叠态变更请求(`v-model:asideCollapsed`);受控时是否真的展开取决于外部是否更新该值 |
|
|
736
742
|
| selectShortcut | `(shortcut: Shortcut)` | 选择快捷指令(继承自 ChatInput) |
|
|
737
743
|
| deleteShortcut | — | 删除已选快捷指令(继承自 ChatInput) |
|
|
738
744
|
| modelChange | `(model: IModelOption)` | 切换模型(继承自 ChatInput) |
|
|
@@ -763,10 +769,10 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
|
|
|
763
769
|
|
|
764
770
|
通过 `v-model:render-mode` 控制容器的渲染行为。`ChatContainer` 会把当前 `renderMode` 注入给后代组件,供内容渲染根据场景收敛交互能力。
|
|
765
771
|
|
|
766
|
-
| `renderMode` | 侧边栏 Tab
|
|
772
|
+
| `renderMode` | 侧边栏 Tab | 底部输入区域 | MessageTools 工具栏 | 说明 |
|
|
767
773
|
| ------------ | ---------------------- | --------------------------------- | --------------------- | -------------------------------- |
|
|
768
774
|
| `Chat` | 正常显示 | 正常显示(ChatInput / ShortcutRender / SelectionFooter) | 全部工具按钮 | 默认对话模式 |
|
|
769
|
-
| `Share` |
|
|
775
|
+
| `Share` | 正常显示(开放只读查看) | **隐藏** | **隐藏**(多选模式) | 分享预览模式;开放流程智能体侧栏详情/证据/执行情况与耗时,仅隐藏「重试/跳过」等交互 |
|
|
770
776
|
| `Test` | 正常显示 | 正常显示 | 过滤掉「分享」按钮 | 测试/嵌入模式,隐藏分享入口 |
|
|
771
777
|
|
|
772
778
|
```vue
|
|
@@ -865,5 +871,5 @@ interface Shortcut {
|
|
|
865
871
|
- [SelectionFooter](/components/input/selection-footer) — 多选操作栏
|
|
866
872
|
- [ToolBtn](/components/feedback/tool-btn) — 侧栏全屏按钮
|
|
867
873
|
- [useFullScreen](/composables/use-full-screen) — 侧栏全屏控制
|
|
868
|
-
- [useGlobalConfig](/composables/use-global-config) — 注入 `size` 与 `
|
|
874
|
+
- [useGlobalConfig](/composables/use-global-config) — 注入 `size`、`supportUpload` 与 `timezone`
|
|
869
875
|
- [主题配置](/theme/theme) — 字号主题 CSS 变量
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
## 组件结构
|
|
29
29
|
|
|
30
30
|
```
|
|
31
|
-
ai-chat-input-container
|
|
31
|
+
ai-chat-input-container(padding: 0 16px 16px,底部间距 16px)
|
|
32
32
|
├── slot#top(容器顶部,在输入框框体外侧)
|
|
33
33
|
├── slot#interrupt(容器顶部,在输入框框体外侧,通常展示中断/审批提示)
|
|
34
34
|
└── chat-input(框体,受 inputMaxHeight 控制)
|
|
@@ -85,15 +85,17 @@ ai-chat-input-container
|
|
|
85
85
|
|
|
86
86
|
## 发送状态(messageStatus)
|
|
87
87
|
|
|
88
|
-
`messageStatus`
|
|
88
|
+
`messageStatus` 控制底部工具栏的按钮渲染,但**输入框为空且没有附件时始终自动置灰禁用**,无论 `messageStatus` 传入什么值。
|
|
89
89
|
|
|
90
|
-
| `messageStatus` |
|
|
90
|
+
| `messageStatus` | 输入框有内容或已有附件时按钮表现 | 输入框空且无附件时 |
|
|
91
91
|
| ----------------------------- | ------------------------------------------------------ | ------------------------ |
|
|
92
92
|
| `complete` / `stop` / `error` | 蓝色发送按钮,点击触发 `onSendMessage` | 灰色禁用 |
|
|
93
93
|
| `streaming` / `pending` / `fetching` | 蓝色停止按钮(Loading 图标),点击触发 `onStopSending` | 蓝色停止按钮(仍可点击) |
|
|
94
94
|
| `disabled` | 灰色禁用,点击无效 | 灰色禁用 |
|
|
95
95
|
|
|
96
|
-
> **实现细节**:组件内部用 `messageState` 计算属性决定实际按钮状态:当 `messageStatus` 为 `pending`、`streaming` 或 `fetching`
|
|
96
|
+
> **实现细节**:组件内部用 `messageState` 计算属性决定实际按钮状态:当 `messageStatus` 为 `pending`、`streaming` 或 `fetching` 时直接使用该状态(确保停止按钮始终可用);否则**已有上传附件时视为可发送**(纯附件消息无需输入文字);再否则当输入为空或仅含空白字符时强制为 `disabled`,其余情况使用 `messageStatus` 的值。`fetching` 时按 Enter **不会**触发发送(避免请求中与 Loading 占位阶段重复提交)。
|
|
97
|
+
|
|
98
|
+
> **纯附件消息**:只上传附件不输入文字时,`onSendMessage` 的 `content` 只含 `binary` 项,**不会**附带空文本段。
|
|
97
99
|
|
|
98
100
|
### onSendMessage 第三参数 options(UserQuestion 上下文)
|
|
99
101
|
|
|
@@ -329,7 +331,7 @@ const handleSendMessage = async (
|
|
|
329
331
|
|
|
330
332
|
**个数与大小校验(与 `FileUploadBtn` 分工)**:
|
|
331
333
|
|
|
332
|
-
- 列表最多保留 **`MAX_UPLOAD_FILES`(
|
|
334
|
+
- 列表最多保留 **`MAX_UPLOAD_FILES`(9)** 个待发送附件;已满时再次选择/拖入/粘贴文件会弹出 **bkui-vue `Message` 错误提示**(`formatUploadNotAddedMessage`),且不会继续入队。
|
|
333
335
|
- 在未满的前提下:空文件、单文件大小 **`>= MAX_UPLOAD_FILE_SIZE`(约 2.4MB)**、或与已有文件重复的项会被跳过;若本轮有任意文件因此未加入列表,会在处理结束后弹出**同一条文案风格**的错误提示,汇总未成功添加的数量。
|
|
334
336
|
- `FileUploadBtn` 仅在按钮层过滤**空文件与单文件超大**,把合法文件以数组形式 `upload` 上来;**个数上限与重复校验**在 `ChatInput` 的 `handleUpload` 中统一处理,避免与按钮层各弹一条提示。
|
|
335
337
|
|
|
@@ -414,7 +416,7 @@ const handleSendMessage = async (
|
|
|
414
416
|
|
|
415
417
|
## 自定义占位符
|
|
416
418
|
|
|
417
|
-
|
|
419
|
+
未传入 `placeholder` 时,组件会按 `skills` / `prompts` / `resources` 是否非空动态生成提示行。传入后完全覆盖,支持多行(换行用 `\n`):
|
|
418
420
|
|
|
419
421
|
```vue
|
|
420
422
|
<template>
|
|
@@ -594,8 +596,8 @@ const handleSendMessage = async (
|
|
|
594
596
|
| shortcuts | `Shortcut[]` | - | - | 快捷指令列表,显示在底部工具栏 |
|
|
595
597
|
| models | `IModelOption[]` | - | - | 可选模型列表,传入后在发送按钮左侧展示模型选择器 |
|
|
596
598
|
| shortcutId | `string` | - | - | 当前选中的快捷指令 ID,匹配时列表收起为已选样式 |
|
|
597
|
-
| placeholder | `string` |
|
|
598
|
-
| inputMaxHeight | `number` | `
|
|
599
|
+
| placeholder | `string` | 动态默认 | - | 编辑器占位符,支持多行;未传时按 skills/prompts/resources 动态拼接 |
|
|
600
|
+
| inputMaxHeight | `number` | `280` | - | 框体最大高度(px),有文件时自动加上文件预览区高度 |
|
|
599
601
|
| defaultUploadFiles | `UploadFile[]` | - | - | 预设已上传的文件列表 |
|
|
600
602
|
| sendDisabledTip | `string` | - | - | 业务阻塞发送时的 tooltip 提示;传入后发送按钮置灰,点击、Enter 与 `triggerSendMessage()` 均不会发送 |
|
|
601
603
|
| supportUpload | `boolean` | `true` | - | 是否显示文件上传按钮 |
|
|
@@ -606,13 +608,17 @@ const handleSendMessage = async (
|
|
|
606
608
|
|
|
607
609
|
### 默认占位符
|
|
608
610
|
|
|
611
|
+
未传入 `placeholder` 时,根据当前 `skills` / `prompts` / `resources` 是否非空动态拼接(有对应能力才显示该行),始终保留换行提示:
|
|
612
|
+
|
|
609
613
|
```
|
|
610
|
-
输入 "/" 唤出 Skill
|
|
611
|
-
输入 "\" 唤出 Prompt
|
|
612
|
-
输入 "@" 唤出 工具和 MCP
|
|
613
|
-
通过 Shift + Enter 进行换行输入
|
|
614
|
+
输入 "/" 唤出 Skill // 仅当 skills 非空
|
|
615
|
+
输入 "\" 唤出 Prompt // 仅当 prompts 非空
|
|
616
|
+
输入 "@" 唤出 工具和 MCP // 仅当 resources 非空
|
|
617
|
+
通过 Shift + Enter 进行换行输入 // 始终显示
|
|
614
618
|
```
|
|
615
619
|
|
|
620
|
+
显式传入 `placeholder`(含空字符串)时完全覆盖上述默认文案。三种列表都为空时,只显示换行提示。
|
|
621
|
+
|
|
616
622
|
### Events
|
|
617
623
|
|
|
618
624
|
| 事件名 | 参数 | 触发时机 |
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
> **能力域**:内容渲染
|
|
20
20
|
|
|
21
|
-
展示被引用文本片段的紧凑条带组件。固定高度 28px,左侧引用图标 + 单行截断文本 + 可选关闭图标,背景灰色(`#f5f7fa
|
|
21
|
+
展示被引用文本片段的紧凑条带组件。固定高度 28px,左侧引用图标 + 单行截断文本 + 可选关闭图标,背景灰色(`#f5f7fa`),hover 背景为 `#eaebf0`。
|
|
22
22
|
|
|
23
23
|
常见于两处:
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
## 组件结构
|
|
29
29
|
|
|
30
30
|
```
|
|
31
|
-
.ai-cite-content(flex,height: 28px,padding: 0 8px,gap: 4px,bg: #f5f7fa,border-radius: 4px,margin-bottom: 4px)
|
|
31
|
+
.ai-cite-content(flex,height: 28px,padding: 0 8px,gap: 4px,bg: #f5f7fa,hover: #eaebf0,border-radius: 4px,margin-bottom: 4px)
|
|
32
32
|
├── CiteIcon(14×14px,color: #979ba5,始终显示)
|
|
33
33
|
├── .ai-cite-content-text(flex: 1,单行截断,color: #979ba5,overflow: hidden,text-overflow: ellipsis)
|
|
34
34
|
│ {{ content }}(Vue 文本插值,XSS 安全)
|
|
@@ -134,7 +134,7 @@ const message = {
|
|
|
134
134
|
|
|
135
135
|
| 元素 | 关键样式 |
|
|
136
136
|
| ------------------------ | --------------------------------------------------------------------------------------------------- |
|
|
137
|
-
| `.ai-cite-content` | `height: 28px`,`padding: 0 8px`,`background: #f5f7fa`,`margin-bottom: 4px`(为下方内容留出间距) |
|
|
137
|
+
| `.ai-cite-content` | `height: 28px`,`padding: 0 8px`,`background: #f5f7fa`,hover `#eaebf0`,`margin-bottom: 4px`(为下方内容留出间距) |
|
|
138
138
|
| `.ai-cite-content-text` | `flex: 1`,`white-space: nowrap`,`overflow: hidden`,`text-overflow: ellipsis`,`color: #979ba5` |
|
|
139
139
|
| `CiteIcon` / `CloseIcon` | `14×14px`,`color: #979ba5`;CloseIcon hover 变为 `#4d4f56` |
|
|
140
140
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
### 关联组件
|
|
7
7
|
- **toolcall-render** — 工具调用详情中渲染描述与参数
|
|
8
|
+
- **tool-message** — 工具返回内容同样由 DescPanel 承载
|
|
8
9
|
- **highlight-keyword** — 键值与文本匹配关键词高亮
|
|
9
10
|
|
|
10
11
|
---
|
|
@@ -26,18 +27,37 @@
|
|
|
26
27
|
## 组件结构
|
|
27
28
|
|
|
28
29
|
```
|
|
29
|
-
.ai-toolcall-desc(flex column,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
.ai-toolcall-desc(flex column,padding: 0 16px,max-height: 300px,overflow-y: auto,
|
|
31
|
+
font-size: 12px,line-height: 20px,color: #4d4f56,background: #f5f7fa,radius: 2px)
|
|
32
|
+
├── .desc-title(sticky top: 0,flex + gap 4px,padding: 12px 0 4px,加粗,背景同面板)
|
|
33
|
+
│ ├── {{ title }}
|
|
34
|
+
│ └── .desc-copy(v-if desc;CopyIcon 14×14,margin-left: auto,默认 visibility: hidden)
|
|
35
|
+
└── .desc-panel(flex column,gap: 4px,padding-bottom: 12px)
|
|
33
36
|
├── [JSON 对象/数组] v-for 逐项渲染 .desc-panel-item
|
|
34
|
-
│ ├── .desc-label → HighlightKeyword(key)
|
|
37
|
+
│ ├── .desc-label → HighlightKeyword(key) + 半角冒号
|
|
35
38
|
│ └── .desc-value → HighlightKeyword(值的文本或 JSON 字符串),`word-break: break-all`
|
|
36
39
|
└── [非 JSON / 解析失败] HighlightKeyword(data),`word-break: break-all`
|
|
37
40
|
```
|
|
38
41
|
|
|
42
|
+
面板整体限高 **300px**,超出后内部滚动,`.desc-title` 吸顶不动。纵向留白由标题的 `padding-top` 与内容区的 `padding-bottom` 承担(容器自身不设上下 padding),避免标题吸顶时上方留白漏出滚动内容。
|
|
43
|
+
|
|
39
44
|
> **说明**:键值与纯文本均通过 `HighlightKeyword` 展示,长内容依赖换行与面板宽度展示,**不再**使用 `v-overflow-tips` 悬停气泡。
|
|
40
45
|
|
|
46
|
+
## 复制原始内容
|
|
47
|
+
|
|
48
|
+
`desc` 有值时,标题右侧渲染复制按钮(`.desc-copy`),默认 `visibility: hidden`,鼠标移入面板后显示,图标默认 `#979ba5`、hover `#3a84ff`:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// 复制的是原始 desc 字符串,而非解析后的展示内容,便于粘贴后二次使用
|
|
52
|
+
const handleCopy = () => {
|
|
53
|
+
if (props.desc) {
|
|
54
|
+
copy(props.desc);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
复制能力来自 [useClipboard](/composables/use-clipboard),复制结果的成功/失败提示由该 composable 统一处理。`desc` 为空时按钮不渲染。
|
|
60
|
+
|
|
41
61
|
## desc 解析规则
|
|
42
62
|
|
|
43
63
|
`data` 是一个 computed,逻辑如下:
|
|
@@ -122,7 +142,7 @@ JSON 数组同样被视为 `object`,以数组索引(`0:`、`1:`…)作为
|
|
|
122
142
|
|
|
123
143
|
## 无 desc
|
|
124
144
|
|
|
125
|
-
`desc`
|
|
145
|
+
`desc` 为可选,不传时面板仅显示标题,内容区域为空,复制按钮也不渲染:
|
|
126
146
|
|
|
127
147
|
## API
|
|
128
148
|
|
|
@@ -130,14 +150,16 @@ JSON 数组同样被视为 `object`,以数组索引(`0:`、`1:`…)作为
|
|
|
130
150
|
|
|
131
151
|
| 属性名 | 类型 | 必填 | 说明 |
|
|
132
152
|
| ------ | -------- | ---- | ----------------------------------------------------------------------------------- |
|
|
133
|
-
| title | `string` | ✓ |
|
|
134
|
-
| desc | `string` | — | 描述内容;尝试 `JSON.parse`,成功且为 `object`
|
|
153
|
+
| title | `string` | ✓ | 面板标题,始终渲染在顶部(吸顶) |
|
|
154
|
+
| desc | `string` | — | 描述内容;尝试 `JSON.parse`,成功且为 `object` 类型时渲染键值对列表,否则渲染纯文本;有值时才渲染复制按钮 |
|
|
135
155
|
|
|
136
156
|
## 使用场景
|
|
137
157
|
|
|
138
|
-
`DescPanel`
|
|
158
|
+
`DescPanel` 主要由 `ToolcallRender` 在展开的详情面板中使用,渲染两块内容:**描述**(`function.description`)与**参数**(`function.arguments`);工具返回结果则由 `ToolMessage` 再包一层 `DescPanel`(标题「返回内容」)展示。通常不需要手动引入,如需独立使用,直接传入 `title` 和 `desc` 即可。
|
|
139
159
|
|
|
140
160
|
## 关联组件
|
|
141
161
|
|
|
142
162
|
- [ToolcallRender](/components/agent/toolcall-render) — 主要使用场景
|
|
143
|
-
- [
|
|
163
|
+
- [ToolMessage](/components/message/tool-message) — 工具返回内容面板
|
|
164
|
+
- [HighlightKeyword](/components/helper/highlight-keyword) — 键值高亮
|
|
165
|
+
- [useClipboard](/composables/use-clipboard) — 复制按钮能力来源
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
|
|
63
63
|
```
|
|
64
64
|
ai-execution-summary
|
|
65
|
-
├── ai-execution-summary-header
|
|
65
|
+
├── ai-execution-summary-header(仅 messageGroups 非空时渲染)
|
|
66
66
|
│ └── Input(关键词搜索框,clearable)
|
|
67
67
|
└── ai-execution-summary-content
|
|
68
68
|
├── 有数据时:
|
|
@@ -73,12 +73,12 @@ ai-execution-summary
|
|
|
73
73
|
│ ├── content-item-messages(MessageRender × N)
|
|
74
74
|
│ └── timeline-line(连接线,最后一项不显示)
|
|
75
75
|
└── 无数据时:
|
|
76
|
-
└── Exception
|
|
76
|
+
└── Exception(scene="part")+「暂无数据」/「搜索结果为空」文案(有关键词时附带「清空搜索」)
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
## 空状态
|
|
80
80
|
|
|
81
|
-
当 `messageGroups`
|
|
81
|
+
当 `messageGroups` 为空数组时,**不渲染搜索 header**,内容区整块展示空态(bkui `Exception` +「暂无数据」;若仍有搜索关键词则为「搜索结果为空」并提供「清空搜索」):
|
|
82
82
|
|
|
83
83
|
## 与 ChatContainer 配合
|
|
84
84
|
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
- **会话级聚合**:拍平当前会话所有 `AssistantMessage.property.artifacts`,以 `outputId` 去重后统一在一个列表内展示
|
|
32
32
|
- **唯一命中**:以 `outputId` 作为会话内唯一键(同 `outputId` 视为同一文件);文件名可能重复,不可作唯一键
|
|
33
33
|
- **关键词搜索**:按文件名实时过滤列表
|
|
34
|
-
-
|
|
34
|
+
- **整块空态**:`artifacts` 为空时不渲染列表与预览区,整块展示 bkui `Exception`「暂无数据」(Tab 常驻,无数据也可正常打开侧栏)
|
|
35
|
+
- **异步取链**:`AIFileInfo` 本身不含 `url` / `previewUrl`,通过 `ChatContainer` 的 `onArtifactClick` 按 `outputId` 获取 `download_url` / `preview_url`(TTL 8 分钟缓存;预览重试会 `force` 刷新)
|
|
35
36
|
- **职责拆分**:
|
|
36
37
|
- **面板本身**:列表、搜索、预览头(文件名 / 图标 / 下载)
|
|
37
38
|
- **`ArtifactPreviewHost`**:按策略加载正文或预览 URL,分派到对应 renderer;展示 loading / empty / error(含重试)
|
|
@@ -165,13 +166,14 @@ ArtifactFileCard(点击文件卡片)
|
|
|
165
166
|
├─ useArtifactPreviewLoader(策略 + fetch / 取链,防竞态)
|
|
166
167
|
└─ HtmlPreview | MarkdownPreview | TxtPreview | UrlIframePreview
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
└─ ensureCustomTab('file-artifact')
|
|
169
|
+
容器初始化
|
|
170
|
+
└─ ensureCustomTab('file-artifact') 常驻挂上(不展开侧栏);因 order:-1 排在首位,
|
|
171
|
+
未主动切换过 Tab 时会成为默认选中面板;无产物时由面板展示整块空态
|
|
170
172
|
```
|
|
171
173
|
|
|
172
174
|
- 文件卡片通过 `useArtifactPreviewConsumer` 注入预览上下文,无 Provider 时卡片不可点击(兜底 `undefined`)
|
|
173
175
|
- `ChatContainer` 通过 `useArtifactPreviewProvider` 提供上下文,并把「打开侧栏 Tab」这一副作用以 `onOpen` 注入,保持 composable 职责单一
|
|
174
|
-
- 侧栏「文件产物」Tab 固定不可关闭,`order: -1`
|
|
176
|
+
- 侧栏「文件产物」Tab 固定不可关闭,`order: -1` 排在「执行情况」之前;**常驻不随产物有无增删**,无产物时由面板展示整块空态
|
|
175
177
|
|
|
176
178
|
## 唯一键规则
|
|
177
179
|
|