切换日光/暗黑模式
094. 抽屉服务、通用表单与 AI 填表
学习目标
这一节为表单编辑服务做准备,并实现 AI 填表能力。
学完后,你应该能理解:
- 抽屉服务和弹窗服务为什么类似;
- 弹窗或抽屉为什么要在组件卸载时自动清理;
- 通用表单如何复用表格列配置;
- 单元格编辑逻辑为什么要抽成公共函数;
- 表单编辑服务如何基于抽屉服务封装;
- 聊天助手如何封装成服务;
- 字段提示词如何帮助 AI 填表;
- AI 返回内容如何写回表单。
表单编辑依赖单选
表单编辑通常需要当前行。
当前行来自单选模块。
所以前面先做了单选。
当用户选中一行后,表单编辑服务就可以拿到这条数据,打开抽屉表单进行编辑。
表单新建也类似。
只是它没有已有行数据,而是打开一份默认新数据。
弹窗服务卸载清理
之前封装过弹窗服务。
这一节先优化它。
优化点是:组件卸载时,自动关闭该组件打开的弹窗。
否则可能出现这种情况:
- 页面打开一个弹窗;
- 用户切换路由;
- 页面组件已经卸载;
- 弹窗还留在屏幕上。
这会造成体验和状态问题。
所以服务内部维护一个关闭函数集合。
组件卸载时,统一执行这些关闭函数。
抽屉服务
抽屉服务和弹窗服务很像。
区别是底层组件从 Modal 换成 Drawer。
它们都需要处理:
- 打开;
- 关闭;
- 标题;
- 内容;
- 底部按钮;
- 确认回调;
- 取消回调;
- 异步确认;
- 组件卸载清理。
所以抽屉服务可以复用弹窗服务的设计思路。
异步确认
抽屉里的确认按钮可能要执行异步逻辑。
例如表单校验、保存接口、文件上传。
如果确认回调返回 false,抽屉不关闭。
这适合表单校验失败的场景。
例如:
ts
onOk: async () => {
const valid = await validate()
return valid
}校验失败就留在当前抽屉,让用户继续修改。
通用表单组件
表格列配置不仅能渲染表格,也能渲染表单。
如果页面字段已经按列配置定义了一遍,就不应该再为表单重复定义一遍。
所以课程里封装通用表单组件。
它可以根据列配置生成表单字段。
例如:
- 输入框列生成输入框;
- 下拉列生成选择器;
- 日期列生成日期选择;
- 文本域列生成文本域;
- 不可编辑列只展示内容。
单元格编辑逻辑抽离
表格单元格和通用表单都需要判断字段怎么编辑。
如果逻辑写在单元格组件里,表单组件就无法复用。
所以把公共逻辑抽成函数。
它负责计算:
- 当前字段是否可编辑;
- 当前字段校验规则;
- 编辑状态下如何渲染;
- 非编辑状态下如何渲染;
- 传给
Form.Item的参数; - 表单编辑时的渲染内容。
这样表格行编辑和通用表单能共用字段协议。
默认值填充逻辑抽离
表格渲染列时,要给字段填默认值。
通用表单渲染字段时,也要给字段填默认值。
所以默认值填充逻辑也要抽成公共函数。
否则表格和表单会出现行为不一致。
例如同一个下拉列,在表格里有默认 options 处理,表单里却没有。
抽出来之后,两边都调用同一个默认值处理函数。
通用表单布局
通用表单支持列数配置。
例如一列、两列、三列。
它不直接使用 Ant Design 默认布局。
而是自己控制表单项排列。
这样同一套字段配置可以适配不同抽屉宽度和页面布局。
例如:
tsx
<AutoForm columns={columns} columnCount={2} />字段会按两列展示。
Form 实例暴露
通用表单内部有 Form 实例。
外部需要调用它来:
- 校验;
- 读取值;
- 设置值;
- 重置。
所以组件通过 ref 或传入 ref 对象,把内部 Form 能力暴露出去。
例如表单服务点击确定时,就要调用通用表单的校验方法。
表单编辑服务
表单编辑服务基于抽屉服务封装。
它接收字段配置和数据对象。
然后在抽屉里渲染通用表单。
用户点击确定时:
- 调用表单校验;
- 校验通过后读取数据;
- 把数据传给调用方;
- 关闭抽屉。
如果校验失败,抽屉不关闭。
这样业务页面只需要调用一个服务,就能打开表单编辑抽屉。
聊天助手服务
AI 填表需要一个聊天入口。
之前 AI 简历里已经有聊天助手组件。
这一节把它封装成服务。
调用服务时,会打开一个抽屉。
抽屉里渲染聊天助手组件。
服务接收:
- 提示词;
- AI 返回消息处理函数;
- 抽屉配置。
这样 AI 助手不再固定写在某个页面里。
需要时可以随时通过服务打开。
流式消息兼容
流式接口最后返回的 chunk 可能只包含 token 使用量。
它的 choices 可能为空。
所以处理流式消息时,要先判断是否有有效内容。
有内容再读取文本。
否则可能在最后一段 token 信息上报错。
这属于 AI 接口集成里常见的小坑。
字段提示词
AI 填表不是把字段名简单丢给模型。
每种字段类型需要提供自己的提示词。
例如下拉列要告诉 AI:
- 字段名;
- 字段标题;
- 字段数据类型;
- 可选项有哪些;
- 应该返回选项值。
日期列要告诉 AI 返回日期格式。
开关列要告诉 AI 返回真值或假值。
这样 AI 才能输出能直接写回表单的数据。
各类字段提示
这一节补齐了更多列类型。
包括:
- 输入框;
- 下拉选择;
- 开关;
- 日期;
- 日期时间;
- 图片;
- 数字;
- 文本;
- 文本域。
不同列不仅要定义显示和编辑方式,还要定义 AI 如何理解它。
这就是 getDescriptionPrompt 这类函数的作用。
标准列不进入表单
有些列是标准列。
例如:
- 索引列;
- 多选列;
- 操作列;
- 自动撑开列。
这些列不应该进入通用表单。
所以列配置里会有标准列标记。
通用表单生成字段时会过滤掉这些列。
否则表单里会出现序号、操作按钮这类不应该编辑的内容。
AI 填表提示词
AI 填表提示词会告诉模型:
- 它是数据解析助手;
- 必须返回对象;
- 只返回可编辑字段;
- 每个字段应该按字段提示理解;
- 必须用固定标记包裹数据;
- 无法提取时要说明原因。
例如要求输出:
text
data start
{ ... }
data end这样前端可以稳定提取中间内容。
样例很重要
提示词里还会提供样例。
样例告诉模型:
- 输入字段是什么;
- 用户描述是什么;
- 期望输出是什么。
对于 AI 开发来说,样例非常关键。
样例越清楚,模型越容易按预期输出。
这也是从传统前端开发进入 AI 功能开发时需要特别适应的地方。
在表单服务里加入 AI 填表
表单编辑抽屉左下角增加一个“AI 填表”按钮。
按钮点击后打开聊天助手服务。
流程是:
- 根据当前表单字段生成提示词;
- 打开助手抽屉;
- 用户输入描述或上传图片;
- AI 返回带标记的数据;
- 前端提取标记中间的 JSON;
- 解析成对象;
- 调用表单实例的
setFieldsValue; - 关闭助手抽屉。
这样 AI 结果会直接填进当前表单。
支持文本和图片
AI 填表既可以处理文字描述,也可以处理图片。
例如用户发一段文字,AI 从文字中提取字段值。
也可以发截图,AI 从截图中识别内容并填表。
这依赖前面多模态聊天能力。
在业务系统里,这种能力常用于从截图、聊天记录、表格图片中快速录入数据。
不一定需要智能体
这一节的 AI 填表没有使用复杂智能体。
它只是:
- 构造提示词;
- 调用模型;
- 解析结果;
- 写回表单。
很多业务 AI 功能都是这种形态。
只有任务非常复杂、需要多步工具调用和决策时,才需要智能体。
对初学者来说,可以先从这种“模型加业务表单”的功能理解 AI 开发。
这一节的核心
这一节把表格字段体系扩展到了通用表单和 AI 填表。
关键链路是:
- 抽屉服务承载表单;
- 通用表单复用列配置;
- 字段编辑逻辑和默认值逻辑抽成公共能力;
- 表单服务负责校验和返回数据;
- 助手服务负责打开 AI 聊天;
- 字段提示词负责告诉 AI 如何输出;
- AI 输出解析后写回 Form。
这让普通表单拥有了 AI 辅助录入能力。