diff --git a/docs/demos/sender/actions-enhanced.vue b/docs/demos/sender/actions-enhanced.vue
index 34de34c32..5c140227d 100644
--- a/docs/demos/sender/actions-enhanced.vue
+++ b/docs/demos/sender/actions-enhanced.vue
@@ -1,35 +1,41 @@
@@ -38,10 +44,8 @@ const handleVoiceFinal = (text: string) => {
v-model="content"
placeholder="输入内容,或使用语音/上传文件..."
mode="multiple"
- :has-external-content="selectedFiles.length > 0"
clearable
@submit="handleSubmit"
- @clear="handleClear"
>
@@ -58,18 +62,6 @@ const handleVoiceFinal = (text: string) => {
-
-
- {{ file.name }}
-
-
-
{{ message }}
@@ -86,11 +78,4 @@ const handleVoiceFinal = (text: string) => {
border-radius: 6px;
color: #1476ff;
}
-
-.file-list {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- margin-top: 12px;
-}
diff --git a/docs/demos/sender/attachments-in-sender.vue b/docs/demos/sender/attachments-in-sender.vue
new file mode 100644
index 000000000..8b53314c7
--- /dev/null
+++ b/docs/demos/sender/attachments-in-sender.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ message }}
+
+
+
+
diff --git a/docs/src/components/sender.md b/docs/src/components/sender.md
index cb5baaaa3..fae1ea436 100644
--- a/docs/src/components/sender.md
+++ b/docs/src/components/sender.md
@@ -189,12 +189,20 @@ TrSender.Suggestion.configure({ items: suggestions, filterFn: customFilter })
通过插槽添加增强按钮(Upload、Voice 等),每个按钮都有独立的配置。
-
-
-附件、图片等内容通常由独立组件维护,不会写入 Sender 的编辑器文本。当用户只上传附件或图片、不输入额外文本时,Sender 无法感知这部分外部内容,会因输入框为空而不显示默认发送按钮。此时可以通过 `hasExternalContent` 告诉 Sender 当前存在外部可提交内容,例如 `:has-external-content="files.length > 0"`。设置后,即使输入框为空,默认发送按钮也会显示,快捷键提交和 `submit()` 方法也会按有内容处理。默认清空按钮仍只根据编辑器文本显示;外部内容数据由业务侧维护,建议由附件或图片列表提供自己的删除入口。
+
**配置详见**:[UploadButton 属性](#uploadbutton)、[VoiceButton 属性](#voicebutton)
+### 上传内容
+
+附件、图片等内容通常由上传按钮或独立列表维护,不会写入 Sender 的编辑器文本。把 `TrAttachments` 放在 `TrSender` 内时会自动注册提交数据;提交时可从 `extra.externalPayloads` 中读取 `source="attachments"` 的 payload,其值为原样透传的 `Attachment[]`,具体过滤或上传失败提示由业务层处理。自定义外部内容组件也可以通过 `useSenderContentRegistration` 注册数据。
+
+:::warning 兼容说明
+`hasExternalContent` 仍可用于控制外部内容场景的可提交状态,但不会生成 `externalPayloads`。
+:::
+
+
+
## 交互定制
### 取消操作
@@ -283,7 +291,7 @@ Sender 提供了多个插槽位置,方便扩展功能:
| enterkeyhint @0.4 | 移动端虚拟键盘回车键提示 | `EnterKeyHint` | `'send'` |
| autoSize | 自动调整高度 | `boolean \| { minRows: number, maxRows: number }` | `{ minRows: 1, maxRows: 5 }` |
| clearable | 是否可清空 | `boolean` | `false` |
-| hasExternalContent @0.5 | 是否存在外部可提交内容,适用于附件、图片等不写入编辑器文本的内容 | `boolean` | `false` |
+| hasExternalContent @0.5 兼容保留 | 是否存在外部可提交内容,仅控制可提交状态,不会生成 `externalPayloads` | `boolean` | `false` |
| maxLength | 最大输入长度 | `number` | `Infinity` |
| showWordLimit | 是否显示字数统计 | `boolean` | `false` |
| submitType | 提交方式 | `'enter' \| 'ctrlEnter' \| 'shiftEnter'` | `'enter'` |
@@ -450,7 +458,7 @@ onSelect: (item) => {
| 事件名 | 说明 | 回调参数 |
| ----------------- | -------------------------------------------------------------------- | --------------------------------------- |
| update:modelValue | 内容更新 | `(value: string)` |
-| submit | 提交内容,返回纯文本和结构化数据(可选) | `(text: string, data?: StructuredData)` |
+| submit | 提交内容,返回纯文本、结构化数据(可选)和额外提交内容(可选) | `(text: string, data?: StructuredData, extra?: SenderSubmitExtra)` |
| clear | 清空内容 | `()` |
| focus | 获得焦点 | `(event: FocusEvent)` |
| blur | 失去焦点 | `(event: FocusEvent)` |
@@ -460,10 +468,12 @@ onSelect: (item) => {
:::tip submit 事件参数说明
- **text**:纯文本内容,适用于简单场景(如直接发送给 AI)
- **data**:结构化数据数组,仅在使用 Template 或 Mention 扩展时返回,包含文本和特殊节点的完整信息
+- **extra**:仅当存在外部 payload 时返回,当前包含 `externalPayloads`
根据业务需求选择使用:
- 简单场景:只使用 `text` 参数
- 复杂场景:使用 `data` 参数提取特殊节点信息或自定义拼接格式
+- 附件等外部内容:使用 `extra.externalPayloads` 读取。Sender 只透传外部内容的 `source` 和 `payload`,不内置解析特定来源,也不按状态过滤
详见:[结构化数据](#结构化数据)
:::
@@ -664,6 +674,15 @@ interface SuggestionTextPart {
// 结构化数据(submit 事件返回)
type StructuredData = TemplateItem[] | MentionStructuredItem[]
+interface SenderExternalPayload {
+ readonly source: string
+ readonly payload: unknown
+}
+
+interface SenderSubmitExtra {
+ externalPayloads: SenderExternalPayload[]
+}
+
// 输入模式
type InputMode = 'single' | 'multiple'
diff --git a/packages/components/src/attachments/index.vue b/packages/components/src/attachments/index.vue
index 8ff809d71..088c8cfa5 100644
--- a/packages/components/src/attachments/index.vue
+++ b/packages/components/src/attachments/index.vue
@@ -1,9 +1,10 @@