add vitepress docs

This commit is contained in:
Timi
2026-09-21 16:05:14 +08:00
parent b435bf992e
commit 37cf38fe27
73 changed files with 7003 additions and 802 deletions
+41
View File
@@ -0,0 +1,41 @@
# AiChatComposer 输入框
对话输入框,按状态在发送、停止与重试之间切换。
## 基础用法
:::preview 基础用法 || 发送后进入生成态,2 秒后自动恢复,可观察按钮的三种形态
demo-preview=../demos/ai-chat-composer/basic.vue
:::
## 何时使用
需要单独摆放输入框时使用。多数情况下直接用 [AiChatPanel](/components/ai-chat-panel) 更省事。
## 三种按钮形态
| 状态 | 按钮 |
| --- | --- |
| 默认 | 发送(`sendText`) |
| `isGenerating` 为真 | 停止(`stopText`,危险色) |
| 有 `lastError` 且 `canRetry` | 错误条 + 重试(`retryText`) |
生成中或 `disabled` 为真时输入框不可编辑,`send` 事件也不会抛出。
## 事件
- `send`:抛出**去除首尾空白后**的内容,抛完自动清空输入框;空内容不抛
- `stop`:点停止按钮
- `retry`:点错误条上的重试
输入框内容用 `v-model` 绑定,`maxLength` 默认 2000。
## 自定义插槽
`send`、`stop`、`error` 三个插槽可以替换对应区域的渲染,都带作用域参数(`disabled`、`onSend`、`onStop`、`error`、`canRetry`)。
## API
<api-table name="AiChatComposer" />
+42
View File
@@ -0,0 +1,42 @@
# AiChatMessageList 消息列表
渲染对话消息,含思考过程、引用与流式光标。
## 基础用法
:::preview 基础用法 || 消息里的 thinkingList 与 citationList 会渲染为思考过程与引用
demo-preview=../demos/ai-chat-message-list/basic.vue
:::
## 何时使用
需要单独控制消息区域的布局时使用。多数情况下直接用 [AiChatPanel](/components/ai-chat-panel) 更省事。
## 消息结构
每条消息是 `AiChatMessage`:
| 字段 | 说明 |
| --- | --- |
| `id` | 唯一标识。 |
| `role` | `"user"` 或 `"assistant"`。 |
| `content` | 正文,按 Markdown 渲染。 |
| `thinkingList` | 思考分段,传给 `AiChatThinking` 展示。 |
| `citationList` | 引用信息。 |
| `createdAt` | 生成时间戳。 |
| `statusText` | 状态文案,如工具调用的当前步骤。 |
| `duration` | 本次生成耗时(毫秒)。 |
## 角色文案
`roleNames` 覆盖默认的「助手 / 我」,需要更复杂的逻辑时用 `roleNameFormatter`。
## 插槽
`welcome`、`message`、`role-name`、`thinking`、`citation`、`message-status`、`assistant-icon`、`user-icon` 可以替换对应区域,都带作用域参数。
## API
<api-table name="AiChatMessageList" />
+70
View File
@@ -0,0 +1,70 @@
# AiChatPanel 对话面板
把消息列表与输入框组装成完整对话界面,由业务侧驱动数据。
## 基础用法
:::preview 基础用法 || 回答由本地假流逐块吐出,可随时点「停止」
demo-preview=../demos/ai-chat-panel/basic.vue
:::
## 何时使用
需要一个开箱即用的对话界面时使用。面板本身是**纯展示组件**——它不发起请求、不维护会话,全部状态由外部传入。
## 与 useAiChat 接线
库提供了 `useAiChat` 组合式函数管理会话与流式消息,把它的返回值直接摊给面板即可:
```vue
<script lang="ts" setup>
import { AiChatPanel, useAiChat } from "timi-tdesign-mobile";
const {
messages, isGenerating, activeToolStatus, lastError, canRetry,
sendMessage, stopGeneration, retryLastMessage
} = useAiChat({
request: ({ message, signal }) => fetchReply(message, signal)
});
</script>
<template>
<ai-chat-panel
:messages="messages"
:is-generating="isGenerating"
:active-tool-status="activeToolStatus"
:last-error="lastError"
:can-retry="canRetry"
@send="sendMessage"
@stop="stopGeneration"
@retry="retryLastMessage"
/>
</template>
```
`request` 需要返回一个 SSE 流式的 `Response`,其余能力(历史会话、错误文案、上下文切换)都通过 `useAiChat` 的可选配置注入,组件侧不用改。
## SSE 事件协议
`useAiChat` 内置了一套事件协议,`event:` 后跟事件名、`data:` 后跟 JSON 或纯文本:
| 事件名(含别名) | 作用 | 载荷取值字段 |
| --- | --- | --- |
| `thinking` / `think` / `agent_thought` | 思考过程分段 | `thought`、`thinking`、`reasoning`、`observation`、`text`、`content` |
| `answer` / `message` / `text` | 回答正文增量 | `answer`、`text`、`content` |
| `tool-status` / `tool_status` | 工具调用状态 | `text`、`message`、`statusText`、`status` |
| `citation` / `source` | 引用信息 | `source`、`dataDomain`、`timeRange`、`caliber`、`generatedAt` |
| `done` / `finish` / `completed` | 生成结束 | `conversationId`、`duration` |
| `error` | 流内错误 | `message`、`code` |
载荷是纯文本时会直接当作内容使用。协议不匹配时可以用 `parseEvent` 自行转换。
## 自定义
`welcome`、`composer`、`tool-status`、`message` 等插槽可以替换对应区域。`composer` 插槽会拿到 `draft`、`on-send`、`on-stop`、`on-retry` 等,便于接入自定义输入框。
## API
<api-table name="AiChatPanel" />
+29
View File
@@ -0,0 +1,29 @@
# AiChatThinking 思考过程
折叠展示模型的思考分段,生成中自动展开。
## 基础用法
:::preview 基础用法 || 逐段追加内容,生成中会自动滚到底部
demo-preview=../demos/ai-chat-thinking/basic.vue
:::
## 何时使用
需要把模型的推理过程单独呈现时使用,通常由 [AiChatMessageList](/components/ai-chat-message-list) 内部调用,也可以单独摆放。
## 行为
- `isGenerating` 为真时展开并跟随滚动到底部,结束后收起
- 内容受 `max-height` 限制,超出时内部滚动
- 容器带 `role="log"` 与 `aria-live="polite"`,屏幕阅读器会播报增量
## 与消息的关系
消息的 `thinkingList` 是一组分段(`{ id, content }`),[AiChatMessageList](/components/ai-chat-message-list) 会把它们拼成完整文本后传进来。
## API
<api-table name="AiChatThinking" />
+41
View File
@@ -0,0 +1,41 @@
# ArticleEditor 文章编辑器
以 `Article` 为数据模型,按正文类型切换纯文本、Markdown 与富文本三种编辑形态。
## 基础用法
:::preview 基础用法 || 切换正文类型会同时替换内容,提交时读取完整文章
demo-preview=../demos/article-editor/basic.vue
:::
## 何时使用
需要在一套表单里同时支持多种正文格式时使用。切换只改 `contentType`,上层不需要关心具体编辑器。
## 数据模型
组件只约束三个字段,其他字段会原样保留:
| 字段 | 说明 |
| --- | --- |
| `contentType` | 正文类型,支持 `TEXT`、`MARKDOWN`、`TIP_TAP`(`TIPTAP` 为兼容写法)。 |
| `content` | 正文内容,随类型分别是纯文本、Markdown 源码或 HTML。 |
| `attachmentList` | 附件列表,元素至少包含 `id`、`name`、`url`。 |
## 附件与媒体
`uploadImage`、`uploadVideo` 负责上传,`resolveAttachmentUrl`、`resolveTempUrl` 负责把附件标识换成可访问地址。四个回调都可选,不传时对应能力自动降级。
## 提交内容
编辑过程中抛出的是实时值,提交时建议调用 `submit()`,它会等待富文本里未完成的上传再返回最终数据:
```ts
const article = await editorRef.value?.submit();
```
## API
<api-table name="ArticleEditor" />
+29
View File
@@ -0,0 +1,29 @@
# ArticleView 文章视图
按 `Article` 的正文类型渲染正文内容。
## 基础用法
:::preview 基础用法 || 把 contentType 换成 TEXT 或 MARKDOWN 会切换渲染分支
demo-preview=../demos/article-view/basic.vue
:::
## 何时使用
需要在详情页只读展示文章正文时使用,与 `ArticleEditor` 共用同一套数据类型。
## 渲染分支
| contentType | 渲染方式 |
| --- | --- |
| `TEXT` | 只读文本域。 |
| `MARKDOWN` | 由 timi-web 的 MarkdownView 渲染。 |
| `TIP_TAP` | 由 [TiptapView](/components/tiptap-view) 渲染。 |
内容为空时统一显示 `emptyText`。
## API
<api-table name="ArticleView" />
+37
View File
@@ -0,0 +1,37 @@
# BottomPopup 底部弹层
从底部升起的操作面板,可带标题与左右按钮。
## 基础用法
:::preview 基础用法 || 弹层从视口底部升起,标题栏在内容滚动时吸顶
demo-preview=../demos/bottom-popup/basic.vue
:::
## 何时使用
需要在移动端承载一组操作或一段表单时使用。它基于 TDesign Mobile 的 `Popup`,因此遮罩、层级与动画都沿用框架行为。
## 按钮只抛事件
左右按钮**不会自动关闭弹层**,只抛出 `leftButtonClick` / `rightButtonClick`,关闭与否由业务决定:
```vue
<bottom-popup
v-model="visible"
title="选择操作"
@right-button-click="handleConfirm"
/>
```
按钮文案传空字符串即可隐藏对应按钮;也可以分别用 `leftButton` / `rightButton` 插槽完全接管,插槽会收到 `onClick`。
## 高度
`height` 默认 `"auto"`,按内容撑开;传具体值(如 `"60vh"`)时内容区滚动、标题栏吸顶。
## API
<api-table name="BottomPopup" />
+36
View File
@@ -0,0 +1,36 @@
# CodeEditor 代码编辑器
带行号、语法高亮与查找替换的代码输入框。
## 基础用法
:::preview 基础用法 || 通过 v-model 绑定内容,实例暴露 openSearch 等方法
demo-preview=../demos/code-editor/basic.vue
:::
## 何时使用
需要让用户输入或查看结构化代码时使用。它不做代码校验,只负责输入、高亮与检索。
## 内容绑定
`modelValue` 与 `value` 都可作为输入源,`value` 优先级更高。输入时同步抛出 `update:modelValue` 与 `change`。
## 实例方法
通过模板引用调用暴露的方法,例如打开查找栏:
```ts
import type { CodeEditorExpose } from "timi-tdesign-mobile";
const editorRef = ref<CodeEditorExpose>();
editorRef.value?.openSearch(true);
```
移动端受限于宽度,代码行会横向滚动而不是折行。
## API
<api-table name="CodeEditor" />
+42
View File
@@ -0,0 +1,42 @@
# DurationPicker 时长选择
按时长值选择并回填,单位与候选项由组件内部推导。
## 基础用法
:::preview 基础用法 || 选择后回填的是毫秒数
demo-preview=../demos/duration-picker/basic.vue
:::
## 何时使用
需要让用户选择一个时间跨度(缓存有效期、超时时长等)时使用。对外只暴露毫秒值,单位换算是内部细节。
## 取值与单位
`modelValue` 是**毫秒数**。组件内置了年 / 天 / 小时 / 分钟 / 秒 / 毫秒六个单位,各自带有取值范围与步长:
| 单位 | 范围 | 步长 |
| --- | --- | --- |
| 年 | 1 - 100 | 1 |
| 天 | 1 - 364 | 1 |
| 小时 | 1 - 23 | 1 |
| 分钟 | 1 - 59 | 1 |
| 秒 | 1 - 59 | 1 |
| 毫秒 | 50 - 950 | 50 |
默认值为 1000 毫秒(1 秒)。
## 两个事件
`update:modelValue` 在滚动选择时触发,`change` 在确认选择时触发:
```vue
<duration-picker v-model="duration" @change="onConfirm" />
```
## API
<api-table name="DurationPicker" />
+38
View File
@@ -0,0 +1,38 @@
# 组件总览
共 15 个组件,分为布局、编辑器、交互与 AI 对话四类。
## 布局组件
| 组件 | 说明 |
| --- | --- |
| [RootLayout](/components/root-layout) | 移动端页面骨架,主体内容之外自动渲染版权与备案信息。 |
| [Space](/components/space) | 控制子元素之间的间距与排列方向,支持分隔符。 |
## 编辑器组件
| 组件 | 说明 |
| --- | --- |
| [CodeEditor](/components/code-editor) | 带行号、语法高亮与查找替换的代码输入框。 |
| [TiptapEditor](/components/tiptap-editor) | 基于 Tiptap 的富文本编辑器,工具栏覆盖媒体、表格、链接与代码块。 |
| [TiptapView](/components/tiptap-view) | Tiptap 内容的只读渲染视图,与编辑器共用同一套样式。 |
| [ArticleEditor](/components/article-editor) | 以 Article 为数据模型,按正文类型切换纯文本、Markdown 与富文本编辑。 |
| [ArticleView](/components/article-view) | 按 Article 的正文类型渲染正文与附件列表。 |
| [NotifyEditor](/components/notify-editor) | 以 NotifyDetail 为数据模型的通知编辑表单,复用文章编辑器能力。 |
| [NotifyView](/components/notify-view) | 渲染通知的正文内容。 |
## 交互组件
| 组件 | 说明 |
| --- | --- |
| [BottomPopup](/components/bottom-popup) | 从底部升起的操作面板,可带标题与左右按钮。 |
| [DurationPicker](/components/duration-picker) | 按时长值选择并回填,单位与候选项由组件内部推导。 |
## AI 对话组件
| 组件 | 说明 |
| --- | --- |
| [AiChatPanel](/components/ai-chat-panel) | 把消息列表与输入框组装成完整对话界面,由业务侧驱动数据。 |
| [AiChatMessageList](/components/ai-chat-message-list) | 渲染对话消息,含思考过程、引用与流式光标。 |
| [AiChatComposer](/components/ai-chat-composer) | 对话输入框,按状态在发送、停止与重试之间切换。 |
| [AiChatThinking](/components/ai-chat-thinking) | 折叠展示模型的思考分段,生成中自动展开。 |
+37
View File
@@ -0,0 +1,37 @@
# NotifyEditor 通知编辑器
以 `NotifyDetail` 为数据模型的通知编辑表单,正文部分复用文章编辑器。
## 基础用法
:::preview 基础用法 || 通知复用文章编辑器,同时保留主题等自有字段
demo-preview=../demos/notify-editor/basic.vue
:::
## 何时使用
需要编辑系统通知、站内信等内容时使用。通知与文章的差别只在元数据,正文能力完全一致。
## 数据模型
`NotifyDetail` 只约束正文相关字段,主题、状态等业务字段由外层维护并原样保留:
| 字段 | 说明 |
| --- | --- |
| `content` | 正文内容。 |
| `contentType` | 正文类型,支持 `TEXT`、`TIP_TAP`。 |
| `attachmentList` | 附件列表。 |
## 提交内容
```ts
const detail = await editorRef.value?.submit();
```
与文章编辑器一致,`submit()` 会等待未完成的媒体上传。
## API
<api-table name="NotifyEditor" />
+19
View File
@@ -0,0 +1,19 @@
# NotifyView 通知视图
渲染通知的正文内容,是 `ArticleView` 在通知场景下的薄封装。
## 基础用法
:::preview 基础用法 || 传入 NotifyDetail 即可渲染正文
demo-preview=../demos/notify-view/basic.vue
:::
## 何时使用
需要在通知详情页只读展示正文时使用。主题、状态等元数据由业务页面自行呈现,组件只负责正文。
## API
<api-table name="NotifyView" />
+23
View File
@@ -0,0 +1,23 @@
# RootLayout 根布局
移动端页面骨架,主体内容之外自动渲染版权与备案信息。
## 基础用法
:::preview 基础用法 || 插槽填充主体内容,底部版权区在窄屏下自适应
demo-preview=../demos/root-layout/basic.vue
:::
## 何时使用
需要一套带页脚版权信息的整页容器时使用。它只负责骨架与页脚,不含导航栏,业务可以自行组合。
## 版权区
底部由 timi-web 的 `Copyright` 组件渲染,`icp` 会链接到工信部网站,`domain` 与 `author` 同时传入时才渲染版权行。
## API
<api-table name="RootLayout" />
+33
View File
@@ -0,0 +1,33 @@
# Space 间距
控制子元素之间的间距与排列方向,支持分隔符。
## 基础用法
:::preview 基础用法 || 尺寸可用预设名或具体数值,数组形式分别指定横向与纵向
demo-preview=../demos/space/basic.vue
:::
## 何时使用
需要给一组元素之间加统一间距时使用。相比手写 `margin`,它把间距收敛到一个属性上,调整时不必逐个改样式。
## 尺寸
`size` 接受三种写法:
| 写法 | 说明 |
| --- | --- |
| `"small"` / `"medium"` / `"large"` | 预设值,分别为 8 / 16 / 24 像素 |
| 数字或带单位的字符串 | 自定义间距,如 `12`、`"1.5rem"` |
| 数组 | 依次表示横向与纵向间距 |
## 分隔符
`separator` 或 `separator` 插槽会在相邻元素之间插入内容,注意**末尾元素之后不会插入**。
## API
<api-table name="Space" />
+37
View File
@@ -0,0 +1,37 @@
# TiptapEditor 富文本编辑器
基于 Tiptap 的富文本编辑器,工具栏覆盖媒体、表格、链接与代码块。
## 基础用法
:::preview 基础用法 || 工具栏按移动端宽度自动换行排列
demo-preview=../demos/tiptap-editor/basic.vue
:::
## 何时使用
需要所见即所得的正文编辑时使用。内容以 HTML 字符串双向绑定,可直接入库。
## 媒体上传
图片与视频通过 `uploadImage`、`uploadVideo` 回调上传,组件不绑定具体接口。拖拽或粘贴文件时会先插入占位内容,上传成功后替换为真实地址。
未完成的媒体会在提交时统一处理,`getPendingMediaCount()` 可查询待处理数量。
## 提交内容
编辑过程中的 `v-model` 是实时值,提交时建议调用 `submit()` 以等待未完成的上传并归一化内容:
```ts
const html = await editorRef.value?.submit();
```
## 移动端差异
工具栏按钮在窄屏下换行排列而不是收进折叠菜单,`v-popup` 提示在触屏下不可用,按钮已带文字或图标语义。
## API
<api-table name="TiptapEditor" />
+23
View File
@@ -0,0 +1,23 @@
# TiptapView 富文本视图
Tiptap 内容的只读渲染视图,与编辑器共用同一套样式与扩展。
## 基础用法
:::preview 基础用法 || 超出 maxHeight 时可滚动查看
demo-preview=../demos/tiptap-view/basic.vue
:::
## 何时使用
需要在详情页、审批流等只读场景渲染富文本时使用。相比直接 `v-html`,它复用了编辑器的扩展与样式,展示与编辑效果一致。
## 空内容
内容为空或规范化后为空字符串时,渲染 `emptyText` 占位文案而不是空白区域。
## API
<api-table name="TiptapView" />