sy-page-sdk
v0.1.3
Published
Custom code page SDK for sy lowcode platform
Downloads
524
Readme
sy-page-sdk
面向 custom_code_page 的前端 SDK。当前版本以“统一 transport + 业务模块 API”为中心,不再推荐页面代码直接拼平台 HTTP 路径、手写 query 字符串,或依赖旧的 form.queryList 心智。
规范源码以 src 为准,README 示例对应的可类型检查版本见 readme.examples.tsx。
开发前先读
page-sdk 负责帮页面屏蔽平台 query 序列化和 envelope 差异,但它不是平台语义本身。
在写页面前,建议先按下面顺序阅读:
- ../../docs/platform-form-api.md
- ../../docs/field-value-shapes.md
- ../../docs/simple-search.md
- ../../docs/advanced-search.md
- 本 README
这样可以避免几个高频错误:
- 猜错
SelectField/MultiSelectField/ 人员字段的值形态 - 手写
searchFieldJson、filters、order字符串 - 把
result.data、data.data、response.data混用 - 把
formInstId错当成id
模块地图
sdk.form- 表单详情、增删改、变更记录、simple search、advanced search、导入导出、数据管理页配置
sdk.user- 用户创建、更新、删除、查询、当前用户、按用户名读取、检索、按部门查询
sdk.role- 角色 CRUD、角色用户列表、角色分配、切换当前平台或应用角色
sdk.permission.formGroup- 表单权限组 CRUD、列表、查看态字段权限读取
sdk.permission.pageGroup- 页面权限组 CRUD、列表、当前用户菜单权限读取
sdk.permission.api- API 权限 CRUD、列表、分配、按角色读取、反查角色
sdk.permission.ui- UI 权限 CRUD、列表、分配、读取当前平台或应用权限
sdk.process- 流程实例读取、终止、审批、回调触发
sdk.dataSource.run- 页面便捷层。会读取
context.page.dataSources,再路由到sdk.form.*
- 页面便捷层。会读取
sdk.request- JSON 请求底层接口
sdk.download- 二进制下载底层接口
React 入口
保留的 React API:
createReactPagePageProviderusePageSdkusePageContextuseNavigationuseMessageuseModalusePagePropsusePageRouteuseDataSourceuseCurrentUseruseFormViewPermissions
useDataSource 仍然可用,但现在只是 sdk.dataSource.run 的轻量封装,不再是 SDK 的核心模型。对于已经声明了 page.dataSources 的读页面,它仍然是默认首选,因为它天然带有 loading / error / refresh。
最小示例
import type { PageListResult } from "sy-page-sdk"
import { createReactPage, useDataSource, usePageSdk } from "sy-page-sdk/react"
type CustomerRecord = {
formInstanceId: string
customerName: string
}
function CustomerPage() {
const sdk = usePageSdk()
const { data, loading, refresh } = useDataSource<
PageListResult<CustomerRecord>
>("customerList", {
immediate: true,
})
const handleOpenDetail = async () => {
const firstCustomerId = data?.data[0]?.formInstanceId
if (!firstCustomerId) return
await sdk.form.getDetail({
formUuid: "FORM_CUSTOMER",
formInstanceId: firstCustomerId,
})
}
return (
<section>
<button type="button" onClick={() => refresh()}>
刷新
</button>
<button type="button" onClick={() => void handleOpenDetail()}>
读取详情
</button>
<div>{loading ? "loading" : `count: ${data?.totalCount || 0}`}</div>
</section>
)
}
export const { mount, unmount, update } = createReactPage(CustomerPage)Transport 模型
页面正常情况下优先使用业务模块;只有在平台新增了 README 尚未封装的接口时,才直接用底层 transport。
const profile = await sdk.request<{ id: string; name: string }>({
path: "/user/current",
method: "get",
})
const exportFile = await sdk.download({
path: `/${sdk.context.app.appType}/v1/form/advancedExport.xlsx`,
method: "get",
query: {
formUuid: "FORM_CUSTOMER",
exportAll: "y",
},
})sdk.request / sdk.download 都会:
- 自动序列化
query - 统一兼容平台的
result型和data + message型 envelope - 对下载接口补齐
blob、fileName、contentType - 复用宿主运行时的鉴权、报错和 request 客户端能力
表单查询
推荐默认使用 advancedSearch,页面代码传结构化对象,SDK 负责把 filters、order、searchFieldJson 等参数序列化为平台要求的格式。
如果你还不确定某个组件的真实查询值结构,先看:
import type { SearchGroup, SearchSortItem } from "sy-page-sdk"
const filters: SearchGroup = {
logic: "AND",
rules: [
{
key: "status",
componentName: "SelectField",
operator: "EQ",
value: "active",
},
{
key: "detailList",
componentName: "SubFormField",
operator: "EXISTS",
value: {
logic: "AND",
rules: [
{
key: "sku",
componentName: "TextField",
operator: "CONTAINS",
value: "license",
},
],
},
},
],
conditions: [
{
logic: "OR",
rules: [
{
key: "level",
componentName: "SelectField",
operator: "EQ",
value: "A",
},
{
key: "owner",
componentName: "TextField",
operator: "EQ",
value: "Alice",
},
],
},
],
}
const order: SearchSortItem[] = [
{ id: "modifiedTime", isAsc: "n" },
{ id: "customerName", isAsc: "y" },
]
const list = await sdk.form.advancedSearch({
formUuid: "FORM_CUSTOMER",
currentPage: 1,
pageSize: 20,
filters,
order,
instanceStatus: "running",
})simple search 和 ID 搜索仍然保留:
const idList = await sdk.form.searchIds<string>({
formUuid: "FORM_CUSTOMER",
currentPage: 1,
pageSize: 50,
search: {
logic: "AND",
rules: [
{
key: "customerName",
componentName: "TextField",
operator: "CONTAINS",
value: "星云",
},
],
},
dynamicOrder: {
id: "modifiedTime",
isAsc: "n",
},
})列表查询成功后,页面通常这样读取结果:
const rows = list.result?.data || []
const totalCount = list.result?.totalCount || 0
const currentPage = list.result?.currentPage || 1如果走 useDataSource("customerList"),则默认直接读取:
const { data } = useDataSource<PageListResult<CustomerRecord>>("customerList")
const rows = data?.data || []用户、角色与权限
import { useCurrentUser, useFormViewPermissions } from "sy-page-sdk/react"
const { user, isGuest, isInternalUser } = useCurrentUser()
const viewPermissions = useFormViewPermissions("FORM_CUSTOMER")
const canEdit = viewPermissions.can("edit")
const canDelete = viewPermissions.can("delete")
const ownerPermission = viewPermissions.getFieldPermission("owner")
const users = await sdk.user.search("alice")
const role = await sdk.role.create({
name: "客户经理",
code: "customer-manager",
scope: "app",
})
if (users.result?.[0]?.id && role.result?.id) {
await sdk.role.assignRoles({
userId: users.result[0].id,
roleIds: [role.result.id],
})
await sdk.permission.pageGroup.getUserMenuPermissions(sdk.context.app.appType)
}
const formGroup = await sdk.permission.formGroup.create({
appType: sdk.context.app.appType,
formUuid: "FORM_CUSTOMER",
name: "客户表单查看组",
type: "view",
roles: [role.result?.id || ""],
})
const pageGroup = await sdk.permission.pageGroup.list({
appType: sdk.context.app.appType,
})
const viewFieldPermissions =
await sdk.permission.formGroup.getViewFieldPermissions({
formUuid: "FORM_CUSTOMER",
})
const viewPermissionSummary =
await sdk.permission.formGroup.getViewPermissionSummary({
formUuid: "FORM_CUSTOMER",
})
const myPagePermissions = await sdk.permission.pageGroup.getUserMenuPermissions(
sdk.context.app.appType,
)公开页会通过平台创建或复用游客账号。页面不要自行推导游客规则,优先读取
PageContext.user.isGuest / PageContext.user.userType,并通过表单查看态权限汇总控制编辑、删除、变更记录和流程入口。
消息通知
页面即时触发通知时,可以使用按通知类型发送的 API。审批节点、定时提醒、表单事件通知仍应优先由 workflow / automation 承接。
await sdk.notification.sendByType({
notificationType: "customer_follow_up",
recipientId: user.id,
payload: {
customerName: "杭州星云科技",
},
channels: ["inapp"],
})
await sdk.notification.batchSendByType({
notificationType: "customer_follow_up",
recipients: [
{
recipientId: "user-1",
payload: {
customerName: "杭州星云科技",
},
},
],
})不要在页面里硬编码钉钉、第三方待办地址、密钥或模板编号;这些由平台消息配置决定。
流程能力
const instance = await sdk.process.getInstance({
instanceId: "PROC-2026-0001",
})
await sdk.process.approveTask({
instanceId: "PROC-2026-0001",
formUuid: "FORM_CUSTOMER",
action: "approved",
comments: "审批通过",
})
await sdk.process.terminateInstance({
processInstanceId: "PROC-2026-0001",
reason: "测试结束",
})
await sdk.process.triggerCallbackTask({
taskId: "TASK-CALLBACK-001",
payload: {
source: "custom-page",
},
})数据管理页配置
const current = await sdk.form.getDataManagementConfig({
formUuid: "FORM_CUSTOMER",
})
await sdk.form.saveDataManagementConfig({
formUuid: "FORM_CUSTOMER",
config: {
...current.result,
showFields: ["customerName", "owner", "status", "level"],
sort: [{ id: "modifiedTime", isAsc: "n" }],
},
})文件流
SDK 不会自动触发浏览器下载,只会返回统一的二进制对象,由页面决定何时下载或预览。
const preview = await sdk.form.importPreview({
formUuid: "FORM_CUSTOMER",
fileBase64,
fileName: "customers.xlsx",
})
const exportFile = await sdk.form.advancedExport({
formUuid: "FORM_CUSTOMER",
filters,
order,
exportAll: "y",
})
const failedFile = await sdk.form.downloadImportFailed({
recordId: "IMP-2026-0001",
})
const exportUrl = URL.createObjectURL(exportFile.blob)PageBinaryResponse 结构:
type PageBinaryResponse = {
blob: Blob
fileName?: string
contentType?: string
headers?: Record<string, string | undefined>
raw?: unknown
}什么时候用 useDataSource
适合:
- 页面已经有
page.dataSources - 页面主要是列表、报表、dashboard 这类读场景
- 只是想复用页面配置里的数据源 key
- 想要拿到现成的
loading / error / refresh
不适合:
- 用户、角色、权限、流程这类业务模块
- 需要导入导出、数据管理配置、文件下载
- 你已经明确知道要调哪个平台能力
这类场景直接调用 usePageSdk() 后使用 sdk.form / sdk.user / sdk.role / sdk.permission / sdk.process 会更清晰。
无论使用 useDataSource 还是 usePageSdk(),正式页面都应展示真实的 empty / error state,不要在运行时回退样例数据。
