yida-canvas-upgrade · git:20261029.142ac00 · 2026-10-29 · sha256 c55ef5614b780828

yida-canvas-upgrade git:20261029.142ac00A

Immutable. This exact content never changes and is served at /api/v1/blob/c55ef5614b780828.

---
name: yida-canvas-upgrade
description: 将基于 JSX 组件 的自定义页面升级/迁移为使用 `YidaCodeCanvas` 组件实现的宜搭自定义页面。适用于用户要求“.oyd.jsx / .oyb.jsx / Jsx 页面转 YidaCodeCanvas”“renderJsx 页面迁移到 YidaCodeCanvas”“把发布产物改为 runtimeCode + importedModules”。不要用于从零编写自定义页面。
---

# 平台 JSX 组件页面迁移到 YidaCodeCanvas 组件实现

完成总结遵循[用户可见总结](../../references/user-facing-summary.md):仅概述本轮业务变化和真实结果,简单修改一句即可;内部记录保留源码、命令和校验细节。

## 核心定位

本技能用于迁移存量页面:把已有的 JSX 组件页面转换为使用 `YidaCodeCanvas` 组件实现的页面,产出等价的 React18 函数组件源码并承载到 `YidaCodeCanvas`。

- 迁移前页面:OpenYida 平台 JSX 组件页面,通常是 `project/pages/src/*.oyd.jsx`、`export function renderJsx()`、`_customState`、`this.utils.yida.*`,`openyida publish` 发布为 `Jsx` 组件;用户称 `.oyb.jsx` 时先按平台 JSX 组件页面需求识别,再确认实际源码后缀。
- 目标实现:页面 Schema 中承载 `YidaCodeCanvas` 组件,组件属性包含 `code`、`runtimeCode`、`importedModules`,运行时执行 `YidaComp`。

## 从老应用主题升级进入

从 `yida-upgrade-app-theme` 进入时,复用已备份的 Schema、源码和已确认的目标页面清单,逐页进行等价迁移。保持原业务逻辑、主要区块结构、字段 ID、请求参数、权限和跳转行为,不借迁移重做页面或更换业务模板。平台数据能力按当前 Canvas 数据桥规范适配,无法证明等价时停止发布,在应用升级清单记录未完成项。源码注入历史表单详情主题时,按已确认范围清理样式及专属监听,保留业务事件。

## 迁移前必须确认

| 检查项 | 命令 / 做法 |
| --- | --- |
| 登录态只读验证 | `openyida env --json` + `openyida login --check-only --json` |
| 原页面源码 | 找到 `.oyd.jsx` / `.jsx` 源文件;不要只看 dist 编译产物 |
| 目标页面 Schema | 先执行 `openyida get-schema <appType> <formUuid>`,再用 create_file / Write / file edit tool 按需保存到 `<projectRoot>/.cache/openyida/canvas-upgrade/<name>-schema.json`;不要用 shell 重定向 |
| YidaCodeCanvas 发布能力 | 已内置:产出的 `.canvas.jsx` 用 `openyida publish <源文件> <appType> <formUuid>` 即自动写入 `YidaCodeCanvas` Schema(`.canvas.jsx` 扩展名识别,CLI 本地用 Babel 编译出 `runtimeCode` + `importedModules`),无需设计器手工添加 |
| 原页面数据依赖 | 列出 `this.utils.yida.*`、`this.dataSourceMap.*`、连接器、外部脚本、全局变量 |

`openyida publish` 已能把 `.canvas.jsx` 发布为 `YidaCodeCanvas` 组件页面;升级的真正门槛在**源码等价改写**(尤其 `this.utils.yida.*` / `dataSourceMap` 在 `YidaCodeCanvas` 组件内没有平台 JSX 组件实例桥对应物),而非发布能力。改写受阻、无法保证等价时,保留源码草案和内部迁移记录,用业务语言说明尚未完成的功能,不要声称已完成升级。

## 可迁移性分级

| 原页面能力 | 迁移建议 |
| --- | --- |
| 纯展示 UI、静态数据、轻交互 | 可直接迁为 `YidaComp` 函数组件 |
| 普通 React 状态 / `_customState` | 改为 `useState` / `useMemo` / `useEffect` |
| `didMount` / `didUnmount` | 改为 `useEffect(() => { ...; return cleanup; }, [])` |
| ECharts / d3 / recharts | 优先使用 `YidaCodeCanvas` 可用资源清单;不在清单内则先补依赖或降级 |
| `this.utils.yida.*` 表单 API | 不能默认照搬;需要通过 props、数据源注入;无法等价迁移时保留历史页面并输出阻塞点 |
| `this.dataSourceMap.*` | 需要确认 YidaCodeCanvas props 是否透传数据源;未验证前不要迁移为可运行承诺 |
| `this.utils.toast/dialog/router` | 改为 antd Message/Modal 或由 props 注入的能力;需验证 |
| 字段组件如 `EmployeeField` | 按 `YidaCodeCanvas` 组件依赖映射规则先做最小验证 |
| `openyida publish` | 仍是最终发布方式:`.oyd.jsx` / `.openyida.jsx` 等平台 JSX 源码发布为 `Jsx` 组件,`.canvas.jsx` 源码(或加 `--canvas`)发布为 `YidaCodeCanvas` 组件。迁移就是把源码改写成 `.canvas.jsx` 后重新 `publish` |

## 输出产物位置

- 可维护的 `.canvas.jsx` 源码放在 `project/pages/src/<页面名>.canvas.jsx`。
- 临时分析、Schema 回读、编译返回值、依赖清单放在 `.cache/openyida/canvas-upgrade/`。
- 不要把一次性 `runtimeCode`、接口抓包、调试 JSON 放到仓库根目录。

## 迁移步骤

1. **盘点原页面**
   - 读取源文件,不从 `project/pages/dist/*.js` 反推。
   - 列出导出的函数、顶层常量、`_customState` 字段、生命周期、API 调用、第三方脚本。
   - 标记依赖 `this` 的能力:`this.utils`、`this.dataSourceMap`、`this.state`、`this.setState`。

2. **判断是否能自动升级**
   - 如果页面主要是 UI + 本地状态 + 白名单图表库,可以继续生成 `.canvas.jsx` 源码。
   - 如果页面强依赖 `this.utils.yida.*` 或设计器数据源,但 YidaCodeCanvas props 未验证,先输出阻塞点和迁移计划。
   - 如果目标诉求其实是字段结构、流程、报表、权限,停止迁移,切到对应配置型技能。

3. **生成 `.canvas.jsx` 源码**
   - 把 `export function renderJsx()` 的 JSX 提取到 `function YidaComp(props)`。
   - 把 `_customState` 拆为 React state;复杂派生数据用 `useMemo`。
   - 把生命周期副作用放进 `useEffect` 并返回 cleanup。
   - 把普通页面 API 适配逻辑抽成 props 调用或明确的 TODO,不要假装可用。
   - 保持 UI 结构和文案尽量不变,先做等价迁移,再考虑重构。

4. **处理依赖**
   - import 只使用 `YidaCodeCanvas` 可用资源清单内的包(能被 CLI 编译识别并注入 `importedModules`)。
   - 对照 `YidaCodeCanvas` 依赖规则检查 `importedModules`。
   - 外部 CDN 脚本要么换成白名单依赖,要么在最小验证页确认可加载。

5. **发布 / 验证 Schema**
   - 用 `openyida publish project/pages/src/<页面名>.canvas.jsx <appType> <formUuid>` 发布:`.canvas.jsx` 自动写入 `YidaCodeCanvas` Schema,CLI 本地用 Babel 编译出 `runtimeCode` + `importedModules`(`code` / `runtimeCode` / `importedModules` 由 CLI 填充,无需手工拼 Schema)。
   - 源码改写受阻、无法保证等价时,保留 `.canvas.jsx` 草案和内部升级记录,不要发布覆盖线上页。
   - 发布后回读 Schema,确认组件树中存在 `YidaCodeCanvas`,且 `runtimeCode` 不是空。

6. **运行验收**
   - 打开真实页面,确认首屏非空。
   - 控制台无依赖缺失、`YidaComp` 未定义、CSS 缺失等错误。
   - 核心交互能触发;移动端至少做一次宽度/弹层检查。
   - 如涉及 `EmployeeField`,按 EmployeeField 验收点逐项验证。

## 转换模式与升级报告

- 转换核心:`_customState` → `useState`/`useMemo`;`didMount`/`didUnmount` → `useEffect` + cleanup;删掉 `forceUpdate`/timestamp 强刷;`this.utils.yida.*`/`dataSourceMap` 抽成 props 或明确 TODO(`YidaCodeCanvas` 组件没有平台 JSX 组件实例桥,不要假装可用);JSX 从 `renderJsx()` 提到 `function YidaComp(props)` 并 `export default`。
- 迁移完成或受阻时保存内部升级记录(含 source/target、status、依赖、schema write path、blockers、验收勾选项)。用户总结按共享规则说明实际变化、结果和影响使用的未完成项;仅用户明确要求技术报告时提供对应细节。

> 📖 before/after 完整转换 JSX 示例 + 升级报告模板 → [references/migration-examples.md](references/migration-examples.md)

## 常见阻塞

| 阻塞 | 处理 |
| --- | --- |
| 源码无法等价改写(`this.utils.yida.*` / `dataSourceMap` 深度耦合) | `YidaCodeCanvas` 组件没有平台 JSX 组件实例桥,需重写为自建 HTTP 桥或 props;未验证前保留草案和内部迁移记录,不发布覆盖 |
| 依赖不在 `YidaCodeCanvas` 可用资源清单 | 补依赖映射、换已支持库,或保留原实现 |
| 原页面强依赖 `this.utils.yida.*` | 需要 props / 数据源注入方案;未验证前不要承诺可运行 |
| 原页面使用宜搭原生字段组件 | 先做最小验证 |
| Schema 回读不是 `YidaCodeCanvas` | 说明 Schema 仍是 `Jsx` 组件,升级未完成 |