@blueking/chat-x 0.0.47-beta.4 → 0.0.48-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.
Files changed (27) hide show
  1. package/dist/components/chat-input/chat-input.vue.d.ts +15 -2
  2. package/dist/components/chat-input/input-attachment/input-attachment.vue.d.ts +4 -2
  3. package/dist/components/chat-input/model-selector/capabilities.d.ts +3 -0
  4. package/dist/components/chat-input/model-selector/index.d.ts +3 -0
  5. package/dist/components/chat-input/model-selector/model-selector-panel.vue.d.ts +26 -0
  6. package/dist/components/chat-input/model-selector/model-selector-trigger.vue.d.ts +14 -0
  7. package/dist/components/chat-input/model-selector/model-selector.vue.d.ts +39 -0
  8. package/dist/components/chat-input/model-selector/types.d.ts +61 -0
  9. package/dist/components/chat-input/model-selector/use-model-selector.d.ts +17 -0
  10. package/dist/components/chat-message/message-container/message-container.vue.d.ts +2 -0
  11. package/dist/components/index.d.ts +3 -1
  12. package/dist/icons/input.d.ts +7 -0
  13. package/dist/index.css +1 -1
  14. package/dist/index.js +2147 -1853
  15. package/dist/index.js.map +1 -1
  16. package/dist/lang/lang.d.ts +5 -1
  17. package/dist/mcp/generated/docs/chat-container.md +189 -74
  18. package/dist/mcp/generated/docs/chat-input.md +57 -0
  19. package/dist/mcp/generated/docs/input-attachment.md +1 -0
  20. package/dist/mcp/generated/docs/message-container.md +47 -0
  21. package/dist/mcp/generated/docs/message-tools.md +5 -1
  22. package/dist/mcp/generated/docs/model-selector.md +157 -0
  23. package/dist/mcp/generated/docs/tool-btn.md +33 -4
  24. package/dist/mcp/generated/index.json +31 -3
  25. package/dist/mcp/index.js +0 -0
  26. package/dist/types/tool.d.ts +6 -2
  27. package/package.json +21 -20
@@ -24,6 +24,8 @@ export declare const lang: {
24
24
  readonly 返回内容: "Return Content";
25
25
  readonly 编辑: "Edit";
26
26
  readonly 深度思考: "Deep Thinking";
27
+ readonly 快速思考: "Quick Thinking";
28
+ readonly 图生文: "Image to Text";
27
29
  readonly '\u56FE\u7247\u52A0\u8F7D\u4E2D...': "Loading image...";
28
30
  readonly 图片加载失败: "Failed to load image";
29
31
  readonly 思考中: "Thinking...";
@@ -103,6 +105,8 @@ export declare const lang: {
103
105
  readonly 检索中: "Searching";
104
106
  readonly 检索完成: "Search Completed";
105
107
  readonly 上传文件: "Upload File";
108
+ readonly 选择模型: "Select model";
109
+ readonly 搜索模型关键字: "Search models";
106
110
  readonly '\u8BF7\u6C42\u4E2D...': "Requesting...";
107
111
  readonly 取消满意: "Cancel satisfied";
108
112
  readonly 取消不满意: "Cancel dissatisfied";
@@ -145,4 +149,4 @@ export declare const lang: {
145
149
  readonly 已回复: "Replied";
146
150
  readonly '\u8BF7\u8F93\u5165...': "Please enter...";
147
151
  };
148
- 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:" | "Calling..." | "Call Success" | "Call Failed" | "Tell us your thoughts" | "What makes you satisfied?" | "What makes you dissatisfied?" | "Return Content" | "Edit" | "Deep Thinking" | "Loading image..." | "Failed to load image" | "Thinking..." | "Thinking Completed" | "Thinking Failed" | "Copy Success" | "Copy Failed" | "Return to bottom" | "Stop generating" | "Stopping" | "Duration" | "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" | "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 Image, up to 3 images supported, max 2.4MB 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" | "Answers" | "Replied" | "Please enter..." | "发送" | "停止" | "问问小鲸" | "复制" | "分享" | "点赞" | "不满意" | "删除" | "引用" | "重新生成" | "重新生成将清空下文内容" | "提交" | "取消" | "预览内容" | "跳转详情" | "调用工具:" | "调用中" | "调用成功" | "调用失败" | "说出您的想法" | "什么原因让你满意?" | "什么原因让你不满意?" | "返回内容" | "编辑" | "深度思考" | "图片加载中..." | "图片加载失败" | "思考中" | "已思考完成" | "思考失败" | "复制成功" | "复制失败" | "返回底部" | "停止生成" | "正在停止" | "耗时" | "参数" | "描述" | "执行情况" | "执行中" | "成功" | "失败" | "挂起" | "待执行" | "详情" | "重试" | "重试中" | "跳过中" | "任务正在重试中,不可跳过" | "任务正在跳过中,不可重试" | "节点" | "节点配置" | "节点输出" | "基础信息" | "流程模板" | "节点名称" | "步骤名称" | "执行方案" | "是否可选" | "失败处理" | "超时控制" | "是" | "否" | "输入参数" | "输出参数" | "参数名" | "参数值" | "名称" | "变量说明" | "结构化输出" | "手动跳过" | "暂无数据" | "调用 MCP:" | "更多" | "算法方案评审单" | "评审中" | "审批中" | "已废弃" | "已批准" | "已通过" | "已取消" | "已过期" | "已拒绝" | "已撤销" | "单据编号" | "提交时间" | "当前处理人" | "无" | "查看单据详情" | "复制单据" | "复制单据链接" | "取消审批" | "已取消审批" | "刷新单据状态" | "单据已取消审批" | "该单据已被拒绝,无法取消" | "该单据已通过,无法取消" | "单据已取消,无需重复点击" | "当前状态无法取消审批" | "当前会话有 {count} 个待审批单,如需继续,请先取消审批" | "暂不支持的中断消息" | "检索中" | "检索完成" | "上传文件" | "请求中..." | "取消满意" | "取消不满意" | "确认删除该回答?" | "删除操作无法撤回,请谨慎操作!" | "预览" | "缩小" | "放大" | "旋转" | "下载" | "抱歉,图片加载失败,可尝试重新加载" | "重置" | "重新加载" | "宽" | "高" | "上传图片" | "搜索 关键字" | "选择日期" | "在对话中定位" | "全选" | "确定" | "上传图片, 最多支持上传 3 个, 最大支持 2.4MB" | "你好,我是小鲸" | "清空搜索" | "搜索结果为空" | "有效证据" | "全屏" | "退出全屏" | "请选择以继续" | "继续" | "收到信息:" | "待审批" | "已审批" | "完成" | "跳过" | "单选" | "多选" | "其他" | "回答内容" | "已回复" | "请输入...";
152
+ 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:" | "Calling..." | "Call Success" | "Call Failed" | "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" | "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 Image, up to 3 images supported, max 2.4MB 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" | "Answers" | "Replied" | "Please enter..." | "发送" | "停止" | "问问小鲸" | "复制" | "分享" | "点赞" | "不满意" | "删除" | "引用" | "重新生成" | "重新生成将清空下文内容" | "提交" | "取消" | "预览内容" | "跳转详情" | "调用工具:" | "调用中" | "调用成功" | "调用失败" | "说出您的想法" | "什么原因让你满意?" | "什么原因让你不满意?" | "返回内容" | "编辑" | "深度思考" | "快速思考" | "图生文" | "图片加载中..." | "图片加载失败" | "思考中" | "已思考完成" | "思考失败" | "复制成功" | "复制失败" | "返回底部" | "停止生成" | "正在停止" | "耗时" | "参数" | "描述" | "执行情况" | "执行中" | "成功" | "失败" | "挂起" | "待执行" | "详情" | "重试" | "重试中" | "跳过中" | "任务正在重试中,不可跳过" | "任务正在跳过中,不可重试" | "节点" | "节点配置" | "节点输出" | "基础信息" | "流程模板" | "节点名称" | "步骤名称" | "执行方案" | "是否可选" | "失败处理" | "超时控制" | "是" | "否" | "输入参数" | "输出参数" | "参数名" | "参数值" | "名称" | "变量说明" | "结构化输出" | "手动跳过" | "暂无数据" | "调用 MCP:" | "更多" | "算法方案评审单" | "评审中" | "审批中" | "已废弃" | "已批准" | "已通过" | "已取消" | "已过期" | "已拒绝" | "已撤销" | "单据编号" | "提交时间" | "当前处理人" | "无" | "查看单据详情" | "复制单据" | "复制单据链接" | "取消审批" | "已取消审批" | "刷新单据状态" | "单据已取消审批" | "该单据已被拒绝,无法取消" | "该单据已通过,无法取消" | "单据已取消,无需重复点击" | "当前状态无法取消审批" | "当前会话有 {count} 个待审批单,如需继续,请先取消审批" | "暂不支持的中断消息" | "检索中" | "检索完成" | "上传文件" | "选择模型" | "搜索模型关键字" | "请求中..." | "取消满意" | "取消不满意" | "确认删除该回答?" | "删除操作无法撤回,请谨慎操作!" | "预览" | "缩小" | "放大" | "旋转" | "下载" | "抱歉,图片加载失败,可尝试重新加载" | "重置" | "重新加载" | "宽" | "高" | "上传图片" | "搜索 关键字" | "选择日期" | "在对话中定位" | "全选" | "确定" | "上传图片, 最多支持上传 3 个, 最大支持 2.4MB" | "你好,我是小鲸" | "清空搜索" | "搜索结果为空" | "有效证据" | "全屏" | "退出全屏" | "请选择以继续" | "继续" | "收到信息:" | "待审批" | "已审批" | "完成" | "跳过" | "单选" | "多选" | "其他" | "回答内容" | "已回复" | "请输入...";
@@ -1,11 +1,12 @@
1
1
  <!-- AI SUMMARY -->
2
2
  ## 快速了解
3
3
 
4
- 完整对话容器,组合消息列表、输入区、快捷指令、执行摘要、分享选择和自定义 Tab。 源码位置:src/components/chat-container/chat-container.vue。
4
+ 完整对话容器,组合消息列表、输入区、模型选择、快捷指令、执行摘要、分享选择和自定义 Tab。 透传 models / selectedModel;支持 welcomeTitle 与 #welcome。 源码位置:src/components/chat-container/chat-container.vue。
5
5
 
6
6
  ### 关联组件
7
7
  - **message-container** — 消息列表与滚动区域
8
8
  - **chat-input** — 对话输入与快捷指令入口
9
+ - **model-selector** — 透传 models / selectedModel,在输入区展示模型选择器
9
10
  - **shortcut-render** — 快捷指令表单浮层
10
11
  - **execution-summary** — 执行摘要侧栏与定位
11
12
  - **selection-footer** — 多选分享底部操作栏
@@ -14,30 +15,23 @@
14
15
  <!-- FULL DOC -->
15
16
 
16
17
  # ChatContainer 聊天容器
17
- ## 源码事实
18
18
 
19
- - **源码位置**:`src/components/chat-container/chat-container.vue`
20
- - **能力域**:对话搭建
21
- - **能力说明**:完整对话容器,组合消息列表、输入区、快捷指令、执行摘要、分享选择和自定义 Tab。
19
+ > **能力域**:对话搭建 | **源码**:`src/components/chat-container/chat-container.vue`
22
20
 
23
- > **能力域**:对话搭建
24
-
25
- 顶层聊天容器组件,整合了 `MessageContainer`(消息列表)、`ChatInput`(输入框)、`ExecutionSummary`(执行摘要面板)、`ShortcutRender`(快捷指令表单)和 `SelectionFooter`(多选操作栏)。提供完整的 AI 对话界面布局能力。
21
+ 顶层聊天容器,整合 `MessageContainer`(消息列表)、`ChatInput`(输入框)、`ExecutionSummary`(执行摘要)、`ShortcutRender`(快捷指令表单)和 `SelectionFooter`(多选操作栏),提供完整 AI 对话界面布局。
26
22
 
27
23
  ## 核心能力
28
24
 
29
- - **分栏布局**:基于 `ResizeLayout` 的可拖拽分栏;**侧栏是否展示 Tab / 执行摘要、以及分栏是否进入折叠样式(`ai-is-collapse`)以 `executionGroups` 与执行情况搜索关键词 `keyword` 共同决定**(`executionGroups` 由 `useMessageGroup` 从消息中过滤工具调用与 FlowAgent 记录;`keyword` 来自 `ExecutionSummary` 的 `@update-keyword`)。当 `executionGroups` 为空且未输入搜索词时,侧栏 Tab 与执行摘要不展示;**用户正在搜索执行情况时(`keyword` 非空),即使暂无执行类消息也会保留侧栏**,避免搜索态被折叠
30
- - **消息分组**:内置 `useMessageGroup` 自动处理消息分组、Tool 合并、Loading 注入
31
- - **输入区状态推导**:传给 `MessageContainer` 与 `ChatInput` 的 `messageStatus` 为内部计算值 `inputStatus`:当分组中存在 id 为 `LOADING_MESSAGE_ID`(`'__loading__'`,由 `useMessageGroup` 注入的占位 Loading 消息)时,对内使用 `MessageStatus.Fetching`;否则使用外部传入的 `messageStatus`。用于在「已发用户消息、尚未流式」阶段与流式中一致地展示停止能力,并避免输入区重复发送
32
- - **待审批发送阻塞**:当消息中存在 `AIDevToolApproval` 且状态为 `pending` / `draft` 的中断项时,`useMessageGroup` 会返回待审批提示,容器在输入区上方展示提示并通过 `ChatInput.sendDisabledTip` 禁止继续发送
33
- - **用户问题中断**:当消息中存在待回答 `UserQuestion` 中断时,容器会在输入区上方挂载 `UserQuestionCard`;结构化作答走 `onInterruptResume`,用户在输入框直接发送时走 `onSendMessage` 并在第三参数附带 skip 用的 `payload`(`status: 'cancelled'`)与 `interrupt`,且不会自动清空输入框
34
- - **执行摘要**:侧边栏展示工具调用 / FlowAgent 执行记录,支持关键词搜索和对话定位
35
- - **侧栏全屏**:Tab 栏右侧提供全屏/退出全屏按钮,基于 `useFullScreen` 将侧栏区域(`.ai-full-screen-wrapper`)以浏览器原生全屏展示;全屏时 Tippy `appendTo` 自动切换为全屏容器,避免 tooltip 被遮挡
36
- - **自定义 Tab**:通过 `useCustomTabProvider` 支持动态添加自定义 Tab(如节点详情)
37
- - **分享模式**:内置消息多选分享流程,选中用户消息后确认分享
38
- - **渲染模式注入**:`renderMode` 会通过内部 Provider 下传给后代内容组件;`Share` 分享态开放流程智能体只读查看(侧栏 Tab / 执行情况 / 节点「详情」「有效证据」/ 耗时均保留),仅隐藏底部输入区与「重试 / 跳过」等交互操作
39
- - **字号主题**:通过 `size` 控制 `small`(默认 12px)/ `normal`(14px)两档字号;根节点设置 `data-ai-size`,子组件通过 CSS 变量(`--ai-font-size` 等)响应式缩放;浮层(Tippy / Teleport)会同步 `document.body.dataset.aiSize`,卸载时自动清理
40
- - **空状态欢迎页**:无消息时展示欢迎语和开场白
25
+ - **分栏布局**:基于 `ResizeLayout`;侧栏 Tab / 执行摘要是否展示,以及是否进入 `ai-is-collapse`,由 `executionGroups` 与搜索词 `keyword` 共同决定。无执行数据且未搜索时隐藏侧栏;搜索中(`keyword` 非空)即使暂无执行消息也保留侧栏
26
+ - **消息分组**:内置 `useMessageGroup`,自动分组、Tool 合并、Loading 注入
27
+ - **输入区状态推导**:对内 `messageStatus` `inputStatus`——分组中存在 `LOADING_MESSAGE_ID`(`'__loading__'`)时用 `MessageStatus.Fetching`,否则用外部 `messageStatus`,保证「已发未流式」阶段也能停止、并避免重复发送
28
+ - **待审批发送阻塞**:存在 `AIDevToolApproval` 且为 `pending` / `draft` 时,输入区上方提示,并通过 `ChatInput.sendDisabledTip` 禁止发送
29
+ - **用户问题中断**:待回答 `UserQuestion` 时挂载 `UserQuestionCard`;结构化作答走 `onInterruptResume`,输入框直接发送走 `onSendMessage`(第三参数带 skip `payload` `interrupt`),且不自动清空输入框
30
+ - **执行摘要 / 侧栏全屏 / 自定义 Tab**:侧栏展示工具调用与 FlowAgent 记录,支持搜索定位;Tab 栏可全屏;`useCustomTabProvider` 支持动态 Tab
31
+ - **模型选择**:透传 `models`、`v-model:selectedModel` `@modelChange` `ChatInput`,传入 `models` 后在发送按钮左侧展示 [ModelSelector](/components/input/model-selector)
32
+ - **分享模式 / 渲染模式**:内置多选分享;`renderMode` 经 Provider 下传。`Share` 态开放侧栏只读查看,隐藏底部输入与「重试 / 跳过」等交互
33
+ - **字号主题**:`size` 为 `small`(默认 12px)/ `normal`(14px);根节点 `data-ai-size`,浮层同步 `document.body.dataset.aiSize`
34
+ - **空状态欢迎页**:无消息时展示 Banner、`welcomeTitle`(默认「你好,我是小鲸」)与 `openingRemark`
41
35
 
42
36
  ## 组件结构
43
37
 
@@ -49,21 +43,18 @@ ai-chat-container(:data-ai-size="size")
49
43
  │ ├── .ai-full-screen-wrapper(全屏目标容器,ref=fullScreenRef)
50
44
  │ │ ├── Tab 标签页
51
45
  │ │ │ ├── 执行情况(默认 Tab)
52
- │ │ │ ├── 自定义 Tab × N(可关闭;标签可由 `getSideTabRenderComponent` 自定义)
53
- │ │ │ └── #setting 插槽 → 全屏/退出全屏 ToolBtn(FullScreenIcon / UnFullScreenIcon)
46
+ │ │ │ ├── 自定义 Tab × N(可关闭;标签可由 getSideTabRenderComponent 自定义)
47
+ │ │ │ └── #setting → 全屏/退出全屏 ToolBtn
54
48
  │ │ ├── ExecutionSummary(执行情况 Tab 内容)
55
- │ │ └── 自定义 Tab 组件(`getSideRenderComponent` 优先,否则 `data.component`;可向子组件注入 #locateButton)
56
- │ └── collapse-button(折叠按钮,CollapsedIcon;折叠时图标旋转,hover 高亮 #3a84ff
49
+ │ │ └── 自定义 Tab 组件(getSideRenderComponent 优先,否则 data.component;可注入 #locateButton)
50
+ │ └── collapse-buttonCollapsedIcon)
57
51
  └── main(主内容区)
58
- ├── MessageContainer(有消息时)
59
- ├── #group 插槽(可选,自定义消息组内容)
60
- ├── #message 插槽(可选,自定义单条消息)
61
- │ └── 消息列表 + 工具栏
62
- ├── 欢迎页(无消息时,容器 .ai-welcome-content)
63
- │ └── welcome 插槽(默认:Banner + 欢迎标题 + 开场白 ContentRender;自定义则整块替换)
64
- ├── SelectionFooter(分享模式时)
52
+ ├── MessageContainer(有消息时;#group / #message 可自定义)
53
+ ├── 欢迎页(无消息时 .ai-welcome-content)
54
+ └── #welcome(默认:Banner + welcomeTitle + openingRemark;自定义则整块替换)
55
+ ├── SelectionFooter(分享模式)
65
56
  ├── ShortcutRender(有快捷指令时)
66
- └── ChatInput(默认状态,待审批时通过 interrupt slot 展示 InputInfoAlert)
57
+ └── ChatInput(透传 models / selectedModel;interrupt 槽展示 UserQuestionCard / InputInfoAlert)
67
58
  ```
68
59
 
69
60
  ## 基础用法
@@ -296,7 +287,7 @@ ai-chat-container(:data-ai-size="size")
296
287
 
297
288
  ## 开场白
298
289
 
299
- 无消息时展示欢迎页,通过 `openingRemark` 设置开场白内容(支持 Markdown):
290
+ 无消息时展示欢迎页:`welcomeTitle` 控制标题(未传时默认「你好,我是小鲸」),`openingRemark` 为开场白(支持 Markdown):
300
291
 
301
292
  ```vue
302
293
  <template>
@@ -304,6 +295,7 @@ ai-chat-container(:data-ai-size="size")
304
295
  v-model="inputValue"
305
296
  :messages="[]"
306
297
  :message-status="messageStatus"
298
+ welcome-title="你好,我是小鲸"
307
299
  opening-remark="你好!我是 AI 小鲸 🐳,可以帮你:\n\n- 编写和优化代码\n- 解答技术问题\n- 分析和调试错误"
308
300
  :on-send-message="handleSendMessage"
309
301
  />
@@ -312,7 +304,7 @@ ai-chat-container(:data-ai-size="size")
312
304
 
313
305
  ### 自定义欢迎内容
314
306
 
315
- 通过 `welcome` 插槽可完全自定义欢迎页内容,插槽参数 `openingRemark` 为传入的开场白文本:
307
+ 通过 `#welcome` 可整块替换默认欢迎区,插槽参数为 `{ openingRemark, welcomeTitle }`:
316
308
 
317
309
  ```vue
318
310
  <template>
@@ -320,12 +312,14 @@ ai-chat-container(:data-ai-size="size")
320
312
  v-model="inputValue"
321
313
  :messages="[]"
322
314
  :message-status="messageStatus"
323
- opening-remark="欢迎使用 AI 助手"
315
+ welcome-title="欢迎使用 AI 助手"
316
+ opening-remark="选择一个快捷入口开始对话"
324
317
  :on-send-message="handleSendMessage"
325
318
  >
326
- <template #welcome="{ openingRemark }">
319
+ <template #welcome="{ openingRemark, welcomeTitle }">
327
320
  <div class="my-welcome">
328
- <h3>{{ openingRemark }}</h3>
321
+ <h3>{{ welcomeTitle }}</h3>
322
+ <p>{{ openingRemark }}</p>
329
323
  <div class="quick-actions">
330
324
  <button @click="handleQuickAction('code')">写代码</button>
331
325
  <button @click="handleQuickAction('debug')">调试</button>
@@ -337,7 +331,7 @@ ai-chat-container(:data-ai-size="size")
337
331
  </template>
338
332
  ```
339
333
 
340
- > **注意**:使用 `welcome` 插槽后,将**整块替换**默认欢迎区(含 Banner 图标、默认欢迎标题与 `openingRemark` 的 `ContentRender` 渲染),需自行编排完整欢迎页;插槽参数 `openingRemark` 仍可用于读取传入的开场白文本。
334
+ > **注意**:使用 `#welcome` 后将**整块替换**默认欢迎区(Banner、标题与开场白的 `ContentRender`),需自行编排完整欢迎页。
341
335
 
342
336
  **渲染效果**
343
337
 
@@ -486,22 +480,103 @@ ai-chat-container(:data-ai-size="size")
486
480
  </template>
487
481
 
488
482
  <script setup lang="ts">
489
- import { type Message } from '@blueking/chat-x';
483
+ import { type IToolBtn, type Message } from '@blueking/chat-x';
490
484
 
491
- const handleConfirmShare = (selectedMessages: Message[]) => {
485
+ // 第二参数 source 为触发多选态的按钮对象,可据此区分 share / save 等不同确认场景
486
+ const handleConfirmShare = (selectedMessages: Message[], source?: IToolBtn) => {
487
+ if (source?.id === 'save') {
488
+ console.log('保存选中的消息:', selectedMessages);
489
+ return;
490
+ }
492
491
  console.log('分享消息:', selectedMessages);
493
492
  };
494
493
  </script>
495
494
  ```
496
495
 
496
+ ### 自定义按钮触发多选(triggerSelection)
497
+
498
+ 除内置「分享」外,任意自定义工具按钮标记 `triggerSelection: true` 后,点击即可复用同一套多选流程(勾选消息 → `SelectionFooter` 确认),确认时同样触发 `confirmShare`。配合 `messageTools` / `updateTools`(合并规则见 [MessageContainer · 自定义消息工具栏](/components/setup/message-container))即可扩展如「保存」「收藏到空间」等批量操作。
499
+
500
+ ```vue
501
+ <template>
502
+ <ChatContainer
503
+ v-model="inputValue"
504
+ :messages="messages"
505
+ message-status="complete"
506
+ :message-tools="customMessageTools"
507
+ :on-agent-action="handleAgentAction"
508
+ @confirm-share="handleConfirmShare"
509
+ />
510
+ </template>
511
+
512
+ <script setup lang="ts">
513
+ import { DownloadIcon, type IToolBtn, type Message } from '@blueking/chat-x';
514
+
515
+ const customMessageTools: IToolBtn[] = [
516
+ // 追加「保存」按钮,点击进入多选态;确认走 confirmShare
517
+ { id: 'save', name: '保存', description: '保存该回答', icon: DownloadIcon, triggerSelection: true },
518
+ ];
519
+
520
+ const handleConfirmShare = (selectedMessages: Message[], source?: IToolBtn) => {
521
+ if (source?.id === 'save') {
522
+ // 处理「保存」批量确认
523
+ }
524
+ };
525
+ </script>
526
+ ```
527
+
528
+ > `triggerSelection` 的按钮不会调用 `onAgentAction`,而是直接进入多选态;未标记该字段(且非 `share`)的按钮仍走 `onAgentAction`。
529
+
497
530
  **渲染效果**(点击 AI 回复工具栏中的「分享」按钮进入多选模式)
498
531
 
499
532
  **分享流程**:
500
533
 
501
- 1. 用户点击消息工具栏中的「分享」按钮
534
+ 1. 用户点击消息工具栏中的「分享」按钮(或任意 `triggerSelection: true` 的自定义按钮)
502
535
  2. 进入多选模式,用户勾选要分享的消息
503
536
  3. 底部 `SelectionFooter` 提供全选、取消、确认操作
504
- 4. 确认后触发 `confirmShare` 事件,携带选中的消息列表
537
+ 4. 确认后触发 `confirmShare` 事件,携带选中的消息列表与触发按钮对象(`source`)
538
+
539
+ ## 模型选择
540
+
541
+ `ChatContainer` 将 `models`、`v-model:selected-model` 与 `@model-change` 透传至内部 [ChatInput](/components/input/chat-input)。传入 `models` 后,发送按钮左侧展示 [ModelSelector](/components/input/model-selector);选中值为模型的 `llm_name`,发送时可读取当前 `selectedModel`。
542
+
543
+ ```vue
544
+ <template>
545
+ <ChatContainer
546
+ v-model="inputValue"
547
+ v-model:selected-model="selectedModel"
548
+ :messages="messages"
549
+ message-status="complete"
550
+ :models="models"
551
+ :on-send-message="handleSendMessage"
552
+ @model-change="handleModelChange"
553
+ />
554
+ </template>
555
+
556
+ <script setup lang="ts">
557
+ import { ref } from 'vue';
558
+ import { ChatContainer, type IModelOption, type Message, type TagSchema } from '@blueking/chat-x';
559
+
560
+ const inputValue = ref('');
561
+ // 选中值为 llm_name
562
+ const selectedModel = ref('GPT-4');
563
+ const messages = ref<Message[]>([]);
564
+ const models: IModelOption[] = [
565
+ { id: 1, llm_name: 'GPT-4', property: { support_thinking: true } },
566
+ { id: 2, llm_name: 'Claude 3', property: { support_thinking_quick: true } },
567
+ { id: 3, llm_name: 'DeepSeek', property: { support_vision: true } },
568
+ ];
569
+
570
+ const handleSendMessage = async (content: string, docSchema: TagSchema) => {
571
+ // 发送时可读取 selectedModel.value
572
+ };
573
+ const handleModelChange = (model: IModelOption) => {
574
+ console.log('切换模型:', model);
575
+ };
576
+ </script>
577
+ ```
578
+
579
+ **渲染效果**(输入区发送按钮左侧可切换模型)
505
580
 
506
581
  ## 快捷指令
507
582
 
@@ -543,29 +618,32 @@ ai-chat-container(:data-ai-size="size")
543
618
 
544
619
  ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`(排除 `enableSelection` 和 `messageGroups`),另外新增:
545
620
 
546
- | 属性名 | 类型 | 默认值 | 说明 |
547
- | ------------------ | ---------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
548
- | chatLoading | `boolean` | — | 整体加载状态,`true` 时显示 Loading 遮罩 |
549
- | commonTippyOptions | `AITippyProps` | — | 通用 Tippy 配置(`appendTo` / `placement` / `zIndex`),传入的选项会注入到所有使用 `v-overflow-tips` 的子组件中 |
550
- | executionTabVisible | `boolean` | `true` | 「执行情况」Tab 是否展示;为 `false` 时从 Tab 栏隐藏,若其正被选中则自动切到首个可见 Tab,内容不再渲染 |
551
- | getSideRenderComponent | `(h, props?) => VNode \| undefined` | — | 自定义侧栏内容区渲染;未返回时使用 `selectedTab.data.component` |
552
- | getSideTabRenderComponent | `(h, tab, { removeCustomTab }) => VNode \| undefined` | — | 自定义侧栏 Tab 标签渲染;未返回时使用默认图标 + 文案 + 关闭按钮 |
553
- | openingRemark | `string` | — | 开场白,无消息时显示,支持 Markdown |
554
- | placement | `'left' \| 'right'` | `'left'` | 侧边栏位置 |
555
- | size | `'normal' \| 'small'` | `'small'` | 字号主题档位:`small` 为 12px 基准,`normal` 为 14px 基准;根节点设置 `data-ai-size` 并注入 `useGlobalConfig` |
556
- | resizeProps | `{ disabled?: boolean; initialDivide?: number \| string; max?: number; min?: number }` | — | 透传给内部 `ResizeLayout` 的可选配置,与默认 `collapsible: false`、`immediate: true`、`min: 400` 合并;`placement` 始终取自本组件 `placement`;`initialDivide` 可为像素数字或百分比等字符串(与 bkui ResizeLayout 一致) |
557
- | onCustomTabChange | `(tab: CustomTab) => Promise<any>` | | 自定义 Tab 切换回调,返回值作为 Tab 组件 props |
558
-
559
- > 完整 Props 列表请参考 [ChatInput](/components/input/chat-input) [MessageContainer](/components/setup/message-container) 文档。
621
+ | 属性名 | 类型 | 默认值 | 说明 |
622
+ | ------------------------- | ------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
623
+ | chatLoading | `boolean` | — | 整体加载状态,`true` 时显示 Loading 遮罩 |
624
+ | commonTippyOptions | `AITippyProps` | — | 通用 Tippy 配置,注入到所有使用 `v-overflow-tips` 的子组件 |
625
+ | executionTabVisible | `boolean` | `true` | 「执行情况」Tab 是否展示;为 `false` 时从 Tab 栏隐藏,若正被选中则切到首个可见 Tab |
626
+ | getSideRenderComponent | `(h, props?) => VNode \| undefined` | — | 自定义侧栏内容区渲染;未返回时使用 `selectedTab.data.component` |
627
+ | getSideTabRenderComponent | `(h, tab, { removeCustomTab }) => VNode \| undefined` | — | 自定义侧栏 Tab 标签渲染;未返回时使用默认图标 + 文案 + 关闭按钮 |
628
+ | models | `IModelOption[]` | — | 可选模型列表(继承自 ChatInput);传入后在发送按钮左侧展示 ModelSelector |
629
+ | openingRemark | `string` | | 开场白,无消息时显示,支持 Markdown |
630
+ | placement | `'left' \| 'right'` | `'left'` | 侧边栏位置 |
631
+ | resizeProps | `{ disabled?: boolean; initialDivide?: number \| string; max?: number; min?: number }` | — | 透传给内部 `ResizeLayout`;与默认 `collapsible: false`、`immediate: true`、`min: 400` 合并;`placement` 始终取自本组件 |
632
+ | size | `'normal' \| 'small'` | `'small'` | 字号主题:`small` 12px / `normal` 14px;根节点设置 `data-ai-size` 并注入 `useGlobalConfig` |
633
+ | welcomeTitle | `string` | — | 欢迎页标题;未传时默认展示「你好,我是小鲸」 |
634
+ | onCustomTabChange | `(tab: CustomTab) => Promise<any>` | — | 自定义 Tab 切换回调,返回值作为 Tab 组件 props |
635
+
636
+ > 其余 Props(如 `messages`、`messageStatus`、`onSendMessage`、`shortcuts` 等)继承自 [ChatInput](/components/input/chat-input) 与 [MessageContainer](/components/setup/message-container)。
560
637
 
561
638
  ### v-model
562
639
 
563
- | 属性名 | 类型 | 说明 |
564
- | ---------------- | --------------------- | ------------------------------------------------------------ |
565
- | modelValue | `string \| TagSchema` | 输入框内容,支持纯文本或标签结构 |
566
- | selectedShortcut | `Shortcut \| null` | 当前选中的快捷指令 |
567
- | cite | `string` | 引用内容 |
568
- | renderMode | `RenderMode` | 渲染模式(默认 `Chat`)。`Share` 分享态开放侧栏只读查看(流程智能体详情/证据/执行情况),隐藏底部输入区与「重试/跳过」等交互;`Test` 模式隐藏分享按钮 |
640
+ | 属性名 | 类型 | 说明 |
641
+ | ---------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
642
+ | modelValue | `string \| TagSchema` | 输入框内容,支持纯文本或标签结构 |
643
+ | selectedShortcut | `Shortcut \| null` | 当前选中的快捷指令 |
644
+ | cite | `string` | 引用内容 |
645
+ | renderMode | `RenderMode` | 渲染模式(默认 `Chat`)。`Share` 开放侧栏只读查看并隐藏底部输入与交互操作;`Test` 隐藏分享按钮 |
646
+ | selectedModel | `string` | 当前选中模型的 `llm_name`,透传至 ChatInput 的 ModelSelector |
569
647
 
570
648
  ### Events
571
649
 
@@ -574,21 +652,22 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
574
652
  | stopStreaming | — | 点击「停止生成」按钮 |
575
653
  | shortcutClose | — | 关闭快捷指令表单 |
576
654
  | shortcutSubmit | `(formModel: Record<string, unknown>)` | 提交快捷指令表单 |
577
- | confirmShare | `(messages: Message[])` | 确认分享,携带选中的消息 |
655
+ | confirmShare | `(messages: Message[], source?: IToolBtn)` | 确认分享/多选,携带选中的消息与触发按钮对象(`source`,用于区分 share/save 等场景) |
578
656
  | collapseChange | `(isCollapse: boolean, width: number)` | 侧边栏折叠/展开状态变化 |
579
657
  | selectShortcut | `(shortcut: Shortcut)` | 选择快捷指令(继承自 ChatInput) |
580
658
  | deleteShortcut | — | 删除已选快捷指令(继承自 ChatInput) |
659
+ | modelChange | `(model: IModelOption)` | 切换模型(继承自 ChatInput) |
581
660
 
582
661
  ### Slots
583
662
 
584
- | 插槽名 | 参数 | 说明 |
585
- | ----------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
586
- | codeHeader | `{ language: string; token: Token[] }` | 代码块头部自定义操作区域,透传给 MessageRender → ContentRender → MarkdownContent → CodeContent |
587
- | default | 消息列表相关绑定(messages 等) | 自定义消息列表区域 |
588
- | group | `{ group: MessageGroup }` | 自定义单个消息组内容,透传至 MessageContainer `#group`;替换默认 Checkbox、消息列表与工具栏 |
589
- | interruptQuestion | `{ question, qIndex, answer, setAnswer, confirm }` | 自定义 UserQuestion 单题渲染,透传至输入区上方 UserQuestionCard `#question` |
590
- | message | `{ message, messageToolsStatus, onInterruptResume }` | 自定义单条消息渲染;自定义渲染中断消息时需继续透传 `onInterruptResume` |
591
- | welcome | `{ openingRemark: string }` | 无消息时自定义欢迎页;传入则替换默认 Banner、标题与开场白区域(整块替换) |
663
+ | 插槽名 | 参数 | 说明 |
664
+ | ----------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
665
+ | codeHeader | `{ language: string; token: Token[] }` | 代码块头部自定义操作区域(定义于类型;透传链路同 MessageRender|
666
+ | default | `{ messages, messageStatus, messageGroups, selectedUserMessages, messageToolsStatus, isShareMode, commonTippyOptions, handleAgentAction, onAgentFeedback, onInterruptResume, onUserAction, onUserInputConfirm, onUserShortcutConfirm }` | 自定义消息列表区域;未提供时渲染默认 `MessageContainer` |
667
+ | group | `{ group: MessageGroup }` | 自定义单个消息组,透传至 MessageContainer `#group`;替换默认 Checkbox、消息列表与工具栏 |
668
+ | interruptQuestion | `{ question, qIndex, answer, setAnswer, confirm }` | 自定义 UserQuestion 单题渲染,透传至 UserQuestionCard `#question` |
669
+ | message | `{ message, messageToolsStatus, onInterruptResume }` | 自定义单条消息;自定义中断消息时需继续透传 `onInterruptResume` |
670
+ | welcome | `{ openingRemark?: string; welcomeTitle?: string }` | 无消息时自定义欢迎页;传入则整块替换默认 Banner、标题与开场白 |
592
671
 
593
672
  ### Expose
594
673
 
@@ -633,7 +712,16 @@ ChatContainer 的 Props 继承自 `ChatInputProps` 和 `MessageContainerProps`
633
712
  ## 类型定义
634
713
 
635
714
  ```typescript
636
- import { ChatContainer, RenderMode, MessageRole, type CustomTab, type MessageGroup, type Shortcut, type Message } from '@blueking/chat-x';
715
+ import {
716
+ ChatContainer,
717
+ RenderMode,
718
+ MessageRole,
719
+ type CustomTab,
720
+ type IModelOption,
721
+ type MessageGroup,
722
+ type Shortcut,
723
+ type Message,
724
+ } from '@blueking/chat-x';
637
725
 
638
726
  // 消息组(由 useMessageGroup 生成)
639
727
  interface MessageGroup {
@@ -651,7 +739,33 @@ interface MessageGroup {
651
739
  interface CustomTab<T = Record<string, unknown>> {
652
740
  label: string;
653
741
  name: string;
654
- data?: T & { messageUid?: string };
742
+ icon?: string;
743
+ order?: number; // 缺省 100;「执行情况」固定 0
744
+ visible?: boolean; // 缺省 true;false 时栏内隐藏,仍可程序化选中
745
+ closable?: boolean; // 缺省 true;「执行情况」强制不可关闭
746
+ data?: T & { messageUid?: string; component?: Component; props?: Record<string, unknown> };
747
+ }
748
+
749
+ // 模型选项(透传至 ChatInput / ModelSelector,贴合后端接口结构;能力标签由 property 派生)
750
+ interface IModelOption {
751
+ id: number;
752
+ llm_code: string;
753
+ llm_name: string; // 展示名,同时作为选中值
754
+ llm_type: string;
755
+ space_auth_mode: string;
756
+ user_auth_mode: string;
757
+ max_token_size: number;
758
+ property: {
759
+ support_thinking?: boolean; // → 深度思考
760
+ support_thinking_quick?: boolean; // → 快速思考
761
+ support_vision?: boolean; // → 图生文
762
+ [key: string]: unknown;
763
+ };
764
+ icon?: string;
765
+ description?: string;
766
+ base_model?: string;
767
+ tag_names?: string[];
768
+ disabled?: boolean; // 前端扩展字段
655
769
  }
656
770
 
657
771
  // 快捷指令
@@ -666,10 +780,11 @@ interface Shortcut {
666
780
 
667
781
  - [MessageContainer](/components/setup/message-container) — 消息列表区域
668
782
  - [ChatInput](/components/input/chat-input) — 输入与快捷指令
783
+ - [ModelSelector](/components/input/model-selector) — 模型选择器(透传 `models` / `selectedModel`)
669
784
  - [ShortcutRender](/components/input/shortcut-render) — 快捷指令表单
670
785
  - [ExecutionSummary](/components/agent/execution-summary) — 执行摘要侧栏
671
786
  - [SelectionFooter](/components/input/selection-footer) — 多选操作栏
672
- - [ToolBtn](/components/feedback/tool-btn) — 侧栏全屏按钮(自定义插槽)
787
+ - [ToolBtn](/components/feedback/tool-btn) — 侧栏全屏按钮
673
788
  - [useFullScreen](/composables/use-full-screen) — 侧栏全屏控制
674
789
  - [useGlobalConfig](/composables/use-global-config) — 注入 `size` 与 `supportUpload`
675
790
  - [主题配置](/theme/theme) — 字号主题 CSS 变量
@@ -8,6 +8,7 @@
8
8
  - **shortcut-btn** — 已选快捷指令以单按钮形式展示并可关闭
9
9
  - **shortcut-render** — 快捷指令含 components 时由外层唤起表单渲染
10
10
  - **chat-container** — 顶层聊天布局中作为输入区子组件
11
+ - **model-selector** — 传入 models 后在发送按钮左侧默认展示模型选择器
11
12
  - **cite-content** — 消息引用区展示选中的上下文片段
12
13
 
13
14
  ---
@@ -38,6 +39,7 @@ ai-chat-input-container
38
39
  ├── FileUploadBtn(仅当 supportUpload 为 true 时显示,在 slot#attachment 外部)
39
40
  ├── 分隔线(仅当 supportUpload 为 true 且有快捷指令时显示)
40
41
  ├── slot#attachment(默认:ShortcutBtns 或已选 ShortcutBtn + 关闭图标)
42
+ ├── slot#before-send(默认:传入 models 时渲染 ModelSelector)
41
43
  └── slot#send-icon(默认:发送/停止图标,仅替换图标,按钮容器保留)
42
44
  ```
43
45
 
@@ -498,6 +500,57 @@ const handleSendMessage = async (
498
500
 
499
501
  **渲染效果**(顶部自定义模型信息与中断提示)
500
502
 
503
+ ## 模型选择
504
+
505
+ 传入 `models` 后,会在发送按钮左侧展示 [ModelSelector](/components/input/model-selector)。选中值(模型的 `llm_name`)通过 `v-model:selected-model` 双向绑定,`@model-change` 可获取完整模型对象。能力标签由组件依据 `property` 自动派生。
506
+
507
+ ```vue
508
+ <template>
509
+ <ChatInput
510
+ v-model="inputValue"
511
+ v-model:selected-model="selectedModel"
512
+ :message-status="messageStatus"
513
+ :models="models"
514
+ :on-send-message="handleSendMessage"
515
+ @model-change="handleModelChange"
516
+ />
517
+ </template>
518
+
519
+ <script setup lang="ts">
520
+ import { ref } from 'vue';
521
+ import { ChatInput, MessageStatus, type IModelOption, type TagSchema } from '@blueking/chat-x';
522
+
523
+ const inputValue = ref('');
524
+ // 选中值为 llm_name
525
+ const selectedModel = ref('GPT-4');
526
+ const messageStatus = ref(MessageStatus.Complete);
527
+ const models: IModelOption[] = [
528
+ { id: 1, llm_name: 'GPT-4', property: { support_thinking: true } },
529
+ { id: 2, llm_name: 'Claude 3', property: {} },
530
+ ];
531
+
532
+ const handleSendMessage = async (content: string, docSchema: TagSchema) => {
533
+ /* 发送时可读取 selectedModel.value */
534
+ };
535
+
536
+ const handleModelChange = (model: IModelOption) => {
537
+ console.log('切换模型:', model);
538
+ };
539
+ </script>
540
+ ```
541
+
542
+ 也可通过 `#model-selector` 插槽完全自定义选择器,插槽参数为 `{ models, selectedModel }`:
543
+
544
+ ```vue
545
+ <template>
546
+ <ChatInput v-model="inputValue" :models="models">
547
+ <template #model-selector="{ models, selectedModel }">
548
+ <span>当前:{{ selectedModel || '未选择' }}(共 {{ models.length }} 个)</span>
549
+ </template>
550
+ </ChatInput>
551
+ </template>
552
+ ```
553
+
501
554
  ## Expose(模板引用)
502
555
 
503
556
  通过 `ref` 获取组件实例后可调用以下方法:
@@ -532,12 +585,14 @@ const handleSendMessage = async (
532
585
  | 属性名 | 类型 | 默认值 | 必填 | 说明 |
533
586
  | ------------------ | -------------------------------------------------------------------------- | -------- | ---- | ------------------------------------------------------- |
534
587
  | modelValue | `string \| TagSchema` | - | ✅ | 编辑器的值,支持 `v-model` |
588
+ | selectedModel | `string` | - | - | 当前选中模型的 `llm_name`,支持 `v-model:selected-model` |
535
589
  | messageStatus | `MessageStatus` | - | - | 消息状态,控制按钮;输入为空时内部强制 `disabled` |
536
590
  | cite | `string` | `''` | - | 引用内容,支持 `v-model:cite`,不为空时显示引用区 |
537
591
  | skills | `ISkillListItem[]` | `[]` | - | Skill 列表,输入 `/` 触发,选中后插入 Skill 标签 |
538
592
  | prompts | `string[]` | `[]` | - | Prompt 模板列表,输入 `\` 触发 |
539
593
  | resources | `IAiSlashMenuItem[]` | `[]` | - | 资源列表,输入 `@` 触发,按 `type` 分组展示 |
540
594
  | shortcuts | `Shortcut[]` | - | - | 快捷指令列表,显示在底部工具栏 |
595
+ | models | `IModelOption[]` | - | - | 可选模型列表,传入后在发送按钮左侧展示模型选择器 |
541
596
  | shortcutId | `string` | - | - | 当前选中的快捷指令 ID,匹配时列表收起为已选样式 |
542
597
  | placeholder | `string` | 见默认值 | - | 编辑器占位符,支持多行 |
543
598
  | inputMaxHeight | `number` | `200` | - | 框体最大高度(px),有文件时自动加上文件预览区高度 |
@@ -563,6 +618,7 @@ const handleSendMessage = async (
563
618
  | 事件名 | 参数 | 触发时机 |
564
619
  | ----------------- | ------------------------------------------------------------------------ | --------------------------------------------------------- |
565
620
  | update:modelValue | `(value: string \| TagSchema, selectedResourceList: IAiSlashMenuItem[])` | 编辑器值变化时触发;第二个参数为当前已选中的 `@` 资源列表 |
621
+ | modelChange | `(model: IModelOption)` | 用户切换模型时触发 |
566
622
  | selectShortcut | `(shortcut: Shortcut)` | 点击底部快捷指令按钮 |
567
623
  | deleteShortcut | - | 点击已选快捷指令旁的关闭按钮 |
568
624
 
@@ -575,6 +631,7 @@ const handleSendMessage = async (
575
631
  | input-header | - | 框体内顶部,替换引用区(`CiteContent`) |
576
632
  | files | `{ files: Partial<UploadFile>[] }` | 文件预览区 |
577
633
  | attachment | - | 底部快捷指令区,`FileUploadBtn` 在其左侧,不受此 slot 影响 |
634
+ | model-selector | `{ models: IModelOption[]; selectedModel: string \| undefined }` | 发送按钮左侧模型选择区,默认渲染 ModelSelector |
578
635
  | send-icon | - | 发送按钮内图标,按钮的点击逻辑和样式仍由组件控制 |
579
636
 
580
637
  ### Expose
@@ -32,6 +32,7 @@ ChatInput 底部附件区布局,承载快捷按钮、文件与发送图标。
32
32
  ### Slots
33
33
 
34
34
  - `default`
35
+ - `before-send`(发送按钮左侧区域,ChatInput 默认在此渲染 ModelSelector)
35
36
  - `send-icon`
36
37
 
37
38
  ### Expose