@skopon-cool/form-sdk
v0.6.1
Published
Skopon form rendering SDK (A2UI + form_definition) with submit helpers
Downloads
1,424
Readme
@skopon-cool/form-sdk
Skopon 表单渲染 SDK:基于 A2UI v0.9 + skopon 自定义 catalog,统一渲染 form_definition、A2UI surface 与增量 message 流,并提供 Ask User 提交能力(默认复制 curl,可选 POST JSON)。
Monorepo 开发(skopon-admin)
本目录是 SDK 唯一源码。发版与修改约定见 PUBLISH.md。
严禁在 front/node_modules/@skopon-cool/form-sdk 改代码并 npm publish。
安装
方式一:一键安装(推荐 Agent 客户端)
安装 meta 包,自动带上 SDK 及全部 peer 依赖(react、antd、@a2ui/* 等):
npm install @skopon-cool/form-sdk-bundle使用方式与主包相同,可从 bundle 直接 import:
import '@skopon-cool/form-sdk-bundle/styles.css'
import { AskUserFormCard, createFormClient } from '@skopon-cool/form-sdk-bundle'方式二:手动安装主包 + peer
若宿主项目已有 React / Ant Design,只需补装 SDK 与 A2UI peer:
npm install @skopon-cool/form-sdk react react-dom antd @a2ui/react @a2ui/web_core @ant-design/iconsdayjs、zod 已作为 SDK 普通依赖随包安装,无需单独安装。
Peer dependencies 说明
| 包 | 说明 |
| -------------------------------- | -------------------------------------------------- |
| react / react-dom | 须与宿主共用同一实例,不可由 SDK 内嵌 |
| antd / @ant-design/icons | 表单控件与图标;SDK 内置 Skopon 主题,也可由宿主全局 ConfigProvider 覆盖 |
| @a2ui/react / @a2ui/web_core | A2UI 渲染栈(SDK 内部使用,宿主无需写 A2UI 代码) |
样式与主题(0.2.0+ 开箱即用)
form-sdk.css 已内置 Skopon 设计令牌(@radix-ui/colors + 语义 CSS 变量)与表单组件样式。无需在宿主复制 tokens.css 或 antdTheme。
import '@skopon-cool/form-sdk/styles.css'
// 或 import '@skopon-cool/form-sdk'(入口侧效自动加载样式)SkoponFormRenderer、AskUserFormCard、SkoponA2uiStreamRenderer 内部已包裹 SkoponFormProvider(墨绿 antd 主题)。也可手动使用:
import { SkoponFormProvider, skoponAntdTheme } from '@skopon-cool/form-sdk'
<SkoponFormProvider locale={zhCN}>
<AskUserFormCard ... />
</SkoponFormProvider>高级定制:SkoponFormProvider 的 theme 可覆盖默认主题;skoponAntdTheme / skoponBrandColors 可单独导出复用。
渲染 form_definition
SkoponFormRenderer 按 doc 内容(非引用)决定是否重建内部 processor;相同内容的 doc 即使用新对象引用传入也不会清空用户已填写的值。若需强制刷新表单,请变更 doc 的实际内容或 surfaceId。
import { SkoponFormRenderer, blocksToA2ui, resolveSurfaceFromFormDefinition } from '@skopon-cool/form-sdk'
const surface = resolveSurfaceFromFormDefinition(formDefinition)
// 或
const surface = blocksToA2ui(formDefinition)
<SkoponFormRenderer doc={surface} interactive />网页展示块(0.5.0+)
web 是不参与表单提交的展示块,通过 SkoponWeb A2UI 组件以内嵌 iframe 展示网页。行内高度默认 360px,可配置范围为 200–1200px;右下角按钮可在大尺寸 Modal 中扩展查看。
const definition = {
blocks: [
{
id: 'company-site',
type: 'web',
label: '公司官网',
help: '点击右下角按钮扩展查看',
webUrl: 'https://example.com',
webHeight: 480,
},
],
}- 支持
http://、https://绝对地址,以及/、./、../开头的同源相对地址。 - 拒绝
javascript:、data:和 protocol-relative 地址;非法地址只显示占位状态,不会写入 iframesrc。 - iframe 不使用
sandbox,以兼容网页脚本、登录和表单能力。仅嵌入可信地址。 - SDK 保证宿主组件和 Modal 不产生横向溢出,但无法修改跨域网页内部的滚动行为。
- 目标站点若设置
X-Frame-Options、CSPframe-ancestors,或被浏览器判定为混合内容,仍可能拒绝嵌入。 - 扩展与收起会重新加载网页;关闭动画期间 SDK 会先卸载 Modal iframe,确保同一地址不会同时运行两份。
A2UI 增量流
import { SkoponA2uiStreamRenderer } from '@skopon-cool/form-sdk'
<SkoponA2uiStreamRenderer messages={incomingMessages} interactive />Ask User(QA / 流程 AI 聊天)
payload 须为 blocksJson({ title?, description?, blocks[] }),与表单编辑器 Blocks Json 同形。前端按 form_unique_id 拉取表单后与 payload.blocks 按 name 交集渲染卡片;payload 中表单外的块不在卡片展示,但提交 curl 时会合并进 body 并以注释标注为额外字段。
鉴权与 Token 缓存
SDK 请求(表单详情、简历搜索、案例列表、文件上传)默认从宿主登录时写入的浏览器缓存读取 token,无需每次手写 getHeaders。
| 项 | 默认值 |
| --- | ------------------------------- |
| 存储 | sessionStorage |
| 键名 | auth_user |
| 字段 | JSON 内的 token |
| API 根地址 | JSON 内可选的 skopon_api_base_url;缺失时使用当前 Origin 的 /api/v1 |
| 请求头 | Authorization: Bearer <token> |
与 skopon-admin 登录约定一致:登录接口返回 token 后写入 auth_user。SDK 宿主可同时写入已包含 /api/v1 的 skopon_api_base_url:
sessionStorage.setItem('auth_user', JSON.stringify({
username,
displayName,
token,
skopon_api_base_url: 'https://admin-test.hibot.lol/api/skopon/api/v1',
}))若宿主使用不同缓存键或字段名,创建 client 时传入 authStorage:
createSkoponSdkClients({
baseUrl: '/api/v1',
authStorage: { storageKey: 'my_session', tokenField: 'accessToken' },
})显式 getHeaders 仍优先于 authStorage(用于自定义鉴权逻辑)。
文件上传
FileUpload 选择文件后会立即调用 POST {skopon_api_base_url}/univ/upload/cdn,通过后端上传至七牛 CDN。例如配置为 https://admin-test.hibot.lol/api/skopon/api/v1 时,最终请求 https://admin-test.hibot.lol/api/skopon/api/v1/univ/upload/cdn。未配置时回退到当前 Origin 的 /api/v1/univ/upload/cdn。
上传请求固定从 sessionStorage.auth_user 读取 token 和 skopon_api_base_url,超时为 120 秒,不受 createSkoponSdkClients 的 baseUrl / getHeaders / authStorage 选项影响。
- 表单字段始终为七牛 URL 数组;即使
maxCount=1也是string[]。 - 历史单字符串值会在加载时转换为单元素数组。
- 上传期间
AskUserFormCard不允许提交;删除上传中项或卸载组件会取消请求。 - 删除表单项只会移除字段 URL,不会删除七牛对象。
- 服务端当前不允许 ZIP、RAR 和 7z;即使编辑器已配置这些类型,上传仍会返回类型错误。
直接使用 SkoponFormRenderer 时,可通过 onUploadingChange 获取所有文件组件的聚合上传状态:
<SkoponFormRenderer
doc={surface}
onUploadingChange={(uploading) => setSubmitDisabled(uploading)}
/>Ask User 完整集成(推荐)
import { AskUserFormCard, createSkoponSdkClients } from '@skopon-cool/form-sdk'
const { fetchDetail, resumeSearch, caseSearch } = createSkoponSdkClients({
baseUrl: '/api/v1',
})
<AskUserFormCard
payload={message.payload}
formUniqueId={message.form_unique_id}
callbackUrl={message.callback_url}
fetchFormDetail={fetchDetail}
resumeSearch={resumeSearch}
caseSearch={caseSearch}
submitMode="curl"
/>resumeSearch:简历多选(resume_multiselect)必需,否则显示「未配置简历搜索服务」caseSearch:案例多选(case_multiselect)必需,否则显示「未配置案例搜索服务」- 简历搜索:
GET /api/v1/univ/resume/search(需univ:resume:search权限) - 案例列表:
GET /api/v1/univ/case/list
单独使用各 client
import {
createFormClient,
createResumeSearchClient,
createCaseSearchClient,
resolveSkoponAuthHeaders,
} from '@skopon-cool/form-sdk'
const headers = resolveSkoponAuthHeaders()
const client = createFormClient({ baseUrl: '/api/v1' })
const resumeSearch = createResumeSearchClient({ baseUrl: '/api/v1' })
const caseSearch = createCaseSearchClient({ baseUrl: '/api/v1' })SkoponFormRenderer 直接使用
渲染含简历/案例块的 surface 时同样需注入:
<SkoponFormRenderer
doc={surface}
resumeSearch={resumeSearch}
caseSearch={caseSearch}
/>旧版最小示例(仅表单详情,无简历/案例块时)
import { AskUserFormCard, createFormClient } from '@skopon-cool/form-sdk'
const client = createFormClient({ baseUrl: '/api/v1' })
<AskUserFormCard
payload={message.payload}
formUniqueId={message.form_unique_id}
callbackUrl={message.callback_url}
fetchFormDetail={client.fetchDetail}
submitMode="curl"
/>未传 resumeSearch / caseSearch 时,对应组件会提示未配置搜索服务。
提交
submitMode: 'curl'(默认):复制 curl 到剪贴板(卡片填值 + 额外字段,extra 段含// 额外字段(未在卡片展示)注释)submitMode: 'post':submitFormJson(callbackUrl, { ...cardValues, ...extraValues })POST 合法 JSON
文件块说明:file 类型字段在 SDK 内仅将文件名写入表单值并随提交发出,不包含文件二进制或 URL。若业务需要真实文件上传,请在宿主侧接入上传 API,或将文件块改为其他采集方式。
独立工具:
import { buildAskUserCurlStatement, buildCurlStatement, submitFormJson } from '@skopon-cool/form-sdk'从 form_bp 拉取详情
import { createFormClient } from '@skopon-cool/form-sdk'
const client = createFormClient({
baseUrl: '/api/v1',
detailPath: '/dev/form/detail',
})
const detail = await client.fetchDetail({ formUniqueId: 'formuid-xxx' })未传 getHeaders 时自动从 sessionStorage['auth_user'].token 读取 Bearer token。
发布
cd sdk/front/form && npm publish --access public
cd sdk/front/form-bundle && npm publish --access public