بنقرة واحدة
yida-custom-page
宜搭自定义页面开发技能,包含宜搭表单 JS API 调用(增删改查/流程/工具类共 27 个)、React 16 JSX 组件开发规范、状态管理模式与编码约束。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
宜搭自定义页面开发技能,包含宜搭表单 JS API 调用(增删改查/流程/工具类共 27 个)、React 16 JSX 组件开发规范、状态管理模式与编码约束。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
宜搭平台退出登录技能,清空本地 Cookie 缓存内容。
宜搭表单页面创建与更新技能,支持创建新表单(saveFormSchemaInfo + saveFormSchema + updateFormConfig)和更新已有表单(getFormSchema + saveFormSchema + updateFormConfig),支持 19 种字段类型(含 SerialNumberField 流水号)和字段增删改操作。
宜搭自定义页面创建技能,通过调用 saveFormSchemaInfo 接口快速创建自定义展示页面。
宜搭表单 Schema 获取技能,通过调用 getFormSchema 接口获取指定表单的完整 Schema 结构,用于分析字段定义、组件配置、确认字段 ID(fieldId)等。
宜搭自定义页面发布技能,将 JSX 源码经 Babel 编译、UglifyJS 压缩后构建 Schema,并通过 saveFormSchema 接口部署到宜搭平台。
宜搭完整应用开发技能,描述从零到一搭建一个完整宜搭应用的全流程,包括创建应用、创建页面、需求分析、编写代码、创建表单、发布部署。
| name | yida-custom-page |
| description | 宜搭自定义页面开发技能,包含宜搭表单 JS API 调用(增删改查/流程/工具类共 27 个)、React 16 JSX 组件开发规范、状态管理模式与编码约束。 |
| license | MIT |
| compatibility | ["opencode","claude-code"] |
| metadata | {"audience":"developers","workflow":"yida-development","version":"1.0.0","tags":["yida","low-code","react","custom-page"]} |
本技能提供在阿里宜搭低代码平台上开发自定义页面的完整能力,涵盖从编码到部署的全流程:
| 能力 | 说明 |
|---|---|
| 表单数据操作 | 通过宜搭前端 JS API(this.utils.yida.*)对表单数据进行增删改查 |
| JSX 组件开发 | 编写 React 16 兼容的 JSX 代码,实现个性化定制页面 |
| AI 能力集成 | 调用大模型 AI 接口(/query/intelligent/txtFromAI.json)实现智能文本生成 |
| 自动编译部署 | 通过工具链将源码编译、压缩,并自动合并到宜搭 Schema 中保存 |
当以下场景发生时使用此技能:
注意:编译和发布功能由
yida-publish-page技能提供,此处仅作流程说明。
场景:将 JSX 源码编译为宜搭可用的格式 依赖:需先安装 yida-publish-page 依赖 命令:
cd .claude/skills/yida-publish-page/scripts && npm install
node babel-transform/transform.js pages/src/my-page.js
场景:编译并发布自定义页面到宜搭平台 命令:
node .claude/skills/yida-publish-page/scripts/publish.js APP_XXX FORM-XXX pages/src/my-page.js
playwright(用于登录态管理)cd .claude/skills/yida-publish/scripts && npm install
pip install playwright && playwright install chromium
node scripts/babel-transform/transform.js <源文件路径>
编译流程:
源文件(.js) → @ali/vu-babel-transform (Babel 转换) → UglifyJS (压缩) → <name>.compile.js
cd .claude/skills/yida-publish-page/scripts
npm install # 首次需要安装依赖
node publish.js <appType> <formUuid> <源文件路径>
部署流程:
编译源码(Babel + UglifyJS) → 代码动态构建 Schema JSON(填入 source/compiled)
→ 调用 yida-login 获取登录态(Cookie 持久化) → 调用 saveFormSchema 接口保存
参数说明:
| 参数 | 说明 | 示例 |
|---|---|---|
appType | 应用 ID | APP_XXX |
formUuid | 表单 ID | FORM-XXX |
源文件路径 | 源码文件路径 | pages/src/xxx.js |
baseUrl无需手动传入,脚本会自动调用login.py获取登录态并从中读取base_url。
以下规范是编写宜搭自定义页面代码的核心约束,必须严格遵守。
宜搭自定义页面的 JSX 组件本质上是 React 类组件中的 render 方法,而非独立的 React 组件。因此存在以下关键约束:
| 约束 | 说明 |
|---|---|
| React 版本 | 必须兼容 React 16,禁止使用 Hooks(useState、useEffect 等) |
| 单文件 | 所有代码写在一个文件中(如 index.js) |
| 三方包引入 | 禁止使用 import/require 语法,如需使用第三方库,必须通过 this.utils.loadScript 加载 CDN 脚本,参考 yida-api.md 的「工具类 API」章节。 |
| 函数导出格式 | 使用 export function xxx() {} 格式导出函数 |
| 样式 | 所有 css 必须写在 renderJsx 的方法中,通过 style 的方式引入 |
this 上下文 | 所有导出函数中的 this 指向宜搭页面的 React 类实例 |
禁止使用 this.setState 管理业务状态 | this.setState 已被覆盖,仅用于 forceUpdate(通过更新 timestamp) |
| JavaScript 版本 | 使用 ES2015 (ES6) 语法,不能高于 ES2015 版本 |
| 必须定义 renderJsx 函数 | renderJsx 是宜搭自定义页面核心渲染函数,也是入口函数,必须严格定义,不要改为其他名称 |
一个完整的宜搭自定义页面源文件必须包含:
_customState 变量以下是一个完整自定义页面示例,包含状态管理、生命周期钩子、渲染函数
// ============================================================
// 状态管理
// ============================================================
const _customState = {
// 在此定义所有业务状态的初始值
count: 0,
loading: false,
};
/**
* 获取状态
* @param {string} [key] - 传入 key 返回单个值,不传返回全部状态的浅拷贝
*/
export function getCustomState(key) {
if (key) {
return _customState[key];
}
return { ..._customState };
}
/**
* 设置状态(合并更新,自动触发重新渲染)
* @param {Object} newState - 需要更新的状态键值对
*/
export function setCustomState(newState) {
Object.keys(newState).forEach(function(key) {
_customState[key] = newState[key];
});
this.forceUpdate();
}
/**
* 强制重新渲染(通过更新 timestamp 触发 React 重渲染)
*/
export function forceUpdate() {
this.setState({ timestamp: new Date().getTime() });
}
// ============================================================
// 生命周期
// ============================================================
/**
* 页面加载完成时调用
* 用于:初始化数据、启动定时器、绑定事件等
*/
export function didMount() {
// 初始化逻辑
}
/**
* 页面卸载时调用
* 用于:清理定时器、解绑事件、释放资源等
*/
export function didUnmount() {
// 清理逻辑
}
export function handleSubmit(e) {
this.setCustomState({ submitted: true });
this.utils.toast({ title: '提交成功', type: 'success' });
}
// ============================================================
// 渲染
// ============================================================
/**
* 页面渲染函数(等同于 React 类组件的 render 方法)
* 注意:必须包含隐藏的 timestamp div 以支持 forceUpdate 机制
*/
export function renderJsx() {
const { timestamp } = this.state;
return (
<div>
{/* 必须保留:用于触发重新渲染 */}
<div style={{ display: "none" }}>{timestamp}</div>
{/* 页面内容写在这里 */}
<div onClick={(e) => {this.handleSubmit(e)}>提交</div>
</div>
);
}
// 获取全部状态(返回浅拷贝)
const state = this.getCustomState();
// 获取单个状态值
const count = this.getCustomState('count');
// 设置状态并自动触发重新渲染
this.setCustomState({ count: count + 1, loading: true });
// 仅触发重新渲染(不修改状态)
this.forceUpdate();
| 钩子函数 | 触发时机 | 典型用途 |
|---|---|---|
didMount() | 页面 DOM 加载渲染完毕 | 初始化数据加载、启动定时器、绑定事件 |
didUnmount() | 页面节点从 DOM 移除 | 清理 setInterval / setTimeout、解绑事件 |
| 变量 | 类型 | 说明 |
|---|---|---|
window.g_config._csrf_token | String | CSRF Token,调用需认证的接口(如 AI 接口、Schema 保存)时必须携带 |
window.loginUser.userId | String | 当前登录用户的工号 |
window.loginUser.userName | String | 当前登录用户的姓名 |
this.state.urlParams | Object | 页面 URL 中的查询参数 |
自定义方法必须用 export function 定义:凡是需要在方法内部使用 this(包括 this.utils.yida.*、this.setCustomState 等)的自定义方法,必须且只能使用 export function 方法名() {} 的形式定义,调用时使用 this.方法名()。禁止使用 const fn = () => {}、const fn = function() {} 等形式定义需要访问 this 的方法,这些形式无法被宜搭运行时正确绑定 this:
// ✅ 正确:export function + this.方法名() 调用
export function didMount() {
this.loadStatistics();
}
export function loadStatistics() {
this.utils.yida.searchFormDatas({ formUuid: 'FORM-XXX', pageSize: 10 });
}
// ❌ 错误①:缺少 export,无法被宜搭运行时识别,this 丢失
export function didMount() {
loadStatistics(); // 直接调用,this 丢失
}
function loadStatistics() {
this.utils.yida.searchFormDatas(...); // 报错:this is undefined
}
// ❌ 错误②:箭头函数/函数表达式形式,缺少 export,无法被宜搭运行时绑定 this,禁止使用
const loadStatistics = () => {
this.utils.yida.searchFormDatas(...); // 报错:this is undefined
};
const loadStatistics = function() {
this.utils.yida.searchFormDatas(...); // 报错:this is undefined
};
【严格禁止】事件绑定必须使用箭头函数包裹:在 renderJsx 中绑定任何事件处理器(onClick、onChange、onSubmit 等)时,必须且只能使用箭头函数 (e) => { this.方法名(e) } 的形式,严禁直接写 this.方法名 作为事件处理器,否则 this 会丢失导致运行时报错:
export function handleSubmit(e) {
this.setCustomState({ submitted: true });
this.utils.toast({ title: '提交成功', type: 'success' });
}
// ✅ 正确:箭头函数包裹,this 正确捕获
export function renderJsx() {
return <button onClick={(e) => { this.handleSubmit(e); }}>提交</button>;
}
// ❌ 错误①:直接传方法引用,this 丢失,运行时报错,绝对禁止!
export function renderJsx() {
return <button onClick={this.handleSubmit}>提交</button>;
}
// ❌ 错误②:使用 .bind(this) 绑定,虽然能运行但不符合规范,禁止使用!
export function renderJsx() {
return <button onClick={function() { this.handleSubmit(); }.bind(this)}>提交</button>;
}
生成代码时的自检清单:检查
renderJsx中所有onClick、onChange、onSubmit等事件属性,确保每一个都是(e) => { this.xxx(e) }形式,不存在任何onClick={this.xxx}的写法。
输入法组合输入处理:使用 _isComposing 标记配合 compositionstart / compositionend 事件,正确处理中文输入法的组合输入状态,避免输入过程中触发提交
定时器清理:在 didUnmount 中必须清理所有通过 setInterval / setTimeout 创建的定时器,防止内存泄漏
错误处理:所有 API 调用(this.utils.yida.*、fetch)必须使用 .catch() 处理异常,并通过 this.utils.toast({ title: message, type: 'error' }) 向用户展示错误提示
样式方式:所有样式通过 JavaScript 对象定义(内联样式),在 renderJsx 中通过 style 属性应用,不使用外部 CSS 文件
异步操作:可以使用 async/await 语法,Babel 编译会自动转换为 ES5 兼容代码
pageSize 上限:调用 searchFormDatas、searchFormDataIds、getProcessInstances、getProcessInstanceIds 等分页接口时,pageSize 最大值为 100,超过会导致接口报错。禁止将 pageSize 设置为超过 100 的值,推荐使用 10~100 之间的合理值。
输入框使用非受控组件:在宜搭环境中,<input> 的 value 属性绑定状态后会触发重渲染导致输入异常。正确做法:使用 defaultValue,在 onChange 中更新 _customState 而不调用 setCustomState:
// ❌ 错误:受控组件,每次输入都触发重渲染导致无法输入
<input value={userAnswer} onChange={function(e) { this.setCustomState({ userAnswer: e.target.value }); }} />
// ✅ 正确:非受控组件,仅静默更新状态,不触发重渲染
<input id="my-input" defaultValue="" onChange={function(e) { _customState.userAnswer = e.target.value; }} />
// 需要清空时通过 DOM 操作
var inputEl = document.getElementById("my-input");
if (inputEl) { inputEl.value = ""; }
DateField 时间戳格式:保存日期字段时,值必须是 时间戳(毫秒),不能是字符串:
// ❌ 错误:字符串格式
dateField_xxx: '2024-01-15'
// ✅ 正确:时间戳格式
dateField_xxx: new Date().getTime()
多端适配:宜搭自定义页面会在 PC 端和移动端同时展示,使用 this.utils.isMobile() 判断设备类型:
const isMobile = this.utils.isMobile();
var styles = {
container: { padding: isMobile ? '12px' : '16px', minHeight: '100vh' },
card: { padding: isMobile ? '12px' : '16px', marginBottom: isMobile ? '8px' : '12px' },
};
清除默认样式:宜搭自定义页面容器有默认 padding 和圆角,需要强制覆盖:
var styles = {
container: { padding: '0 16px', borderRadius: '0 !important', minHeight: '100vh' },
};
性能优化:
onChange 都调用 setCustomState,可直接写入 _customState 静默更新forceUpdaterenderJsx 顶部定义事件处理函数,避免每次渲染都创建新的内联函数调试技巧:
// 打印当前状态到控制台
console.log('当前状态:', _customState);
// 弹窗提示(适合快速验证逻辑)
this.utils.toast({ title: '调试信息', type: 'info' });
iframe 嵌入表单 URL 规范:在自定义页面中通过 iframe 嵌入宜搭表单时,需使用正确的 URL 格式:
| 场景 | URL 格式 |
|---|---|
| 表单提交页 | {base_url}/{appType}/submission/{formUuid} |
| 数据管理页(列表) | {base_url}/{appType}/workbench/{formUuid}?iframe=true |
| 数据管理页(指定视图) | {base_url}/{appType}/workbench/{formUuid}?viewUuid={viewUuid}&iframe=true |
// ❌ 错误:formDetail 是表单详情页,不是数据列表
const wrongUrl = `${baseUrl}/${appType}/formDetail/${formUuid}`;
// ✅ 正确:workbench 是运行态数据管理页
const listUrl = `${baseUrl}/${appType}/workbench/${formUuid}?iframe=true`;
viewUuid可选,从宜搭「数据管理」→「报表视图」页面的 URL 中获取,不传则使用默认视图。
通过 this.utils.yida.<方法名>(params) 调用,所有接口返回 Promise。
| 方法 | 说明 | 必填参数 |
|---|---|---|
saveFormData | 新建表单实例 | formUuid, appType, formDataJson |
updateFormData | 更新表单实例 | formInstId, updateFormDataJson |
deleteFormData | 删除表单实例 | formUuid |
getFormDataById | 根据实例 ID 查询详情 | formInstId |
searchFormDatas | 按条件搜索表单实例详情列表 | formUuid |
searchFormDataIds | 按条件搜索表单实例 ID 列表 | formUuid |
getFormComponentDefinationList | 获取表单定义 | formUuid |
常用示例 — 新建表单数据:
this.utils.yida.saveFormData({
formUuid: 'FORM-XXX',
appType: window.pageConfig.appType,
formDataJson: JSON.stringify({
textField_xxx: '单行文本',
textareaField_xxx: '多行文本',
}),
}).then(function(res) {
console.log('新建成功,实例ID:', res.result);
}).catch(function(err) {
this.utils.toast({ title: err.message, type: 'error' });
}.bind(this));
常用示例 — 搜索表单数据:
this.utils.yida.searchFormDatas({
formUuid: 'FORM-XXX',
searchFieldJson: JSON.stringify({ textField_xxx: '查询值' }),
currentPage: 1,
pageSize: 10,
}).then(function(res) {
// res.data: [{ formUuid, formInstId, formData: { textField_xxx: '值' } }]
// res.totalCount: 符合条件的总数
console.log('查询结果:', res.data);
}).catch(function(err) {
this.utils.toast({ title: err.message, type: 'error' });
}.bind(this));
| 方法 | 说明 | 必填参数 |
|---|---|---|
startProcessInstance | 发起流程 | formUuid, processCode, formDataJson |
updateProcessInstance | 更新流程实例 | processInstanceId, updateFormDataJson |
deleteProcessInstance | 删除流程实例 | processInstanceId |
getProcessInstanceById | 根据实例 ID 查询流程详情 | processInstanceId |
getProcessInstances | 按条件搜索流程实例详情列表 | — |
getProcessInstanceIds | 按条件搜索流程实例 ID 列表 | — |
以下接口用于表单页面的创建和配置,通过 HTTP 请求调用:
| 方法 | 说明 | 调用方式 |
|---|---|---|
saveFormSchemaInfo | 创建空白表单 | POST /dingtalk/web/{appType}/query/formdesign/saveFormSchemaInfo.json |
getFormSchema | 获取表单 Schema | GET /alibaba/web/{appType}/_view/query/formdesign/getFormSchema.json |
saveFormSchema | 保存表单 Schema | POST /dingtalk/web/{appType}/_view/query/formdesign/saveFormSchema.json |
updateFormConfig | 更新表单配置 | POST /dingtalk/web/{appType}/query/formdesign/updateFormConfig.json |
完整参数说明请参考 yida-api.md 的「表单设计类 API」章节。
以下接口用于调用大模型 AI 文本生成能力:
| 方法 | 说明 | 调用方式 |
|---|---|---|
txtFromAI | AI 文本生成 | POST /query/intelligent/txtFromAI.json |
主要参数:_csrf_token(CSRF 令牌)、prompt(提示词)、skill(技能类型,如 ToText)、maxTokens(最大返回 token 数)
完整参数说明和示例请参考 model-api.md。
以下工具函数通过 this.utils.<方法名>() 调用,无需 yida 命名空间:
| 方法 | 用途 | 典型场景 |
|---|---|---|
toast | 轻提示 | 操作成功/失败提示、loading 状态 |
dialog | 对话框 | 确认操作、复杂内容展示 |
formatter | 格式化 | 日期、金额、手机号格式化 |
getDateTimeRange | 获取时间范围 | 按日/月/周筛选数据 |
getLoginUserId / getLoginUserName | 获取当前用户 | 记录操作人、数据权限控制 |
getLocale | 获取语言环境 | 多语言适配 |
isMobile | 判断移动端 | 响应式布局适配 |
isSubmissionPage | 判断是否提交页面 | 页面逻辑区分 |
isViewPage | 判断是否查看页面 | 页面逻辑区分 |
openPage | 打开新页面 | 页面跳转、外链打开 |
router.push | 页面路由跳转工具 | 页面路由跳转、避免新开页面 |
previewImage | 图片预览 | 图片查看、多图轮播 |
loadScript | 动态加载脚本 | 引入第三方库(如二维码生成) |
完整参数说明和示例请参考 yida-api.md 的「工具类 API」章节。
| Skill | 说明 | 用法 |
|---|---|---|
| yida-login | 登录态管理(Cookie 持久化 + 扫码登录) | python3 .claude/skills/yida-login/scripts/login.py |
| yida-publish-page | 编译源码 + 构建 Schema + 发布到宜搭 | node .claude/skills/yida-publish-page/scripts/publish.js <appType> <formUuid> <源文件路径> |
| yida-page-config | 页面配置(URL 验证、公开访问/分享配置) | node .claude/skills/yida-page-config/scripts/verify-short-url.js <appType> <formUuid> /o/xxx |
cd .claude/skills/yida-publish-page/scripts
npm install # 首次需要安装依赖
node publish.js <appType> <formUuid> <源文件路径>
处理流程:
@ali/vu-babel-transform 将 JSX 转换为 ES5 + UglifyJS 压缩source 和 compiled 填入 actions.moduleyida-login 获取登录态(Cookie 持久化,首次需扫码登录)saveFormSchema 接口保存 Schemanode .claude/skills/yida-publish-page/scripts/babel-transform/transform.js <源文件路径>
输入 JSX 源文件,输出编译压缩后的 <name>.compile.js(与源文件同目录)。