openyida 2026.7.27-beta.1 → 2026.7.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +45 -47
- package/yida-skills/skills/yida-canvas-custom-page/references/canvas-authoring-examples.md +2 -2
- package/yida-skills/skills/yida-canvas-custom-page/references/canvas-design-system.md +11 -11
- package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +14 -14
- package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +23 -32
- package/yida-skills/skills/yida-canvas-custom-page/references/dependencies-and-cdn.md +6 -26
- package/yida-skills/skills/yida-canvas-custom-page/references/employeefield-verification.md +52 -23
- package/yida-skills/skills/yida-canvas-custom-page/references/native-components-bridge.md +22 -22
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +10 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yida-canvas-custom-page
|
|
3
|
-
description: 宜搭 Code Canvas /
|
|
3
|
+
description: 宜搭 Code Canvas / 代码画布自定义页面开发规范,是现代 React18 自定义页面的默认链路。用于官网、看板、工作台、列表、详情、门户壳、可视化、hooks 交互,以及用户明确提到 code canvas、代码画布、YidaCodeCanvas、runtimeCode、importedModules、门户组件、数据管理视图、成员、部门或上传组件的场景。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 宜搭 Code Canvas 自定义页面开发
|
|
@@ -12,22 +12,22 @@ Code Canvas 是宜搭的代码画布自定义页面链路:以 `YidaCodeCanvas`
|
|
|
12
12
|
相较普通 `.oyd.jsx` 自定义页,Code Canvas 更适合:
|
|
13
13
|
|
|
14
14
|
- 现代 React hooks 交互、图表、动效、复杂状态。
|
|
15
|
-
-
|
|
16
|
-
-
|
|
15
|
+
- 首版页面生成:官网、看板、工作台、列表、详情、门户壳。
|
|
16
|
+
- 需要 React18 函数组件、状态隔离和现代前端体验的页面。
|
|
17
17
|
- 只需要通过 HTTP / 连接器读写数据的页面。
|
|
18
18
|
- 需要在 Canvas 内受控接入门户、成员、部门、上传等宜搭运行态组件的页面。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
普通自定义页面使用 `yida-custom-page`:适用于用户明确要求 JSX/Jsx 普通页面,或页面需要 `this.$(fieldId)` 双向绑定、`this.utils.yida.*`、`this.dataSourceMap`、提交流程深度耦合等普通页面实例桥能力。
|
|
21
21
|
|
|
22
22
|
## 运行时事实
|
|
23
23
|
|
|
24
24
|
- Canvas 源码写成 `.canvas.jsx` / `.canvas.tsx`,`openyida publish` 会自动走 Canvas 链路。
|
|
25
|
-
- 页面源码路径按 Bash cwd 选择:从仓库根执行命令时用 `project/pages/src
|
|
25
|
+
- 页面源码路径按 Bash cwd 选择:从仓库根执行命令时用 `project/pages/src/...`;cwd 已是 `<workspace>/project` 时用 `pages/src/...`。
|
|
26
26
|
- `runtimeCode` 在宿主页真实 `window` 中执行,入口必须返回 `YidaComp` / `YidaComp.default` / 组件函数。
|
|
27
27
|
- 推荐入口写法是 `function YidaComp(props) { ... }`,或 `const App = ...; export default App;`。CLI 已兼容 `const/let/class YidaComp; export default YidaComp`,但生成新代码时优先避开同名默认导出,减少不同 Canvas 运行态装配器下的重复声明风险。
|
|
28
28
|
- Canvas 组件没有普通页面实例上下文;数据读写通过 fetch、开放 API、连接器代理或显式 props 数据桥完成。
|
|
29
29
|
- 第三方依赖走白名单;React、antd、ahooks、d3、recharts、Radix、framer-motion 等可按规则 import。
|
|
30
|
-
-
|
|
30
|
+
- 宜搭运行态组件通过“先探测、可用再增强、不可用就 fallback、值统一归一化”接入;以 `window.Deep` / `window.DeepYida` 探测为主,`window.YidaNativeComponents` 作为兼容入口。嵌入门户数据管理视图时使用 `DataManageViews`,并显式传入目标表单 `form.value/formUuid`。
|
|
31
31
|
|
|
32
32
|
> 依赖白名单和运行时细节见 [dependencies-and-cdn.md](references/dependencies-and-cdn.md) 与 [employeefield-verification.md](references/employeefield-verification.md)。
|
|
33
33
|
|
|
@@ -40,8 +40,8 @@ Code Canvas 是宜搭的代码画布自定义页面链路:以 `YidaCodeCanvas`
|
|
|
40
40
|
| 需要门户 topBanner / quickEntry / 数据卡片 | 使用本技能,按“门户组件桥”接入,必要时 fallback 自绘 |
|
|
41
41
|
| 需要成员、部门、附件上传、图片上传 | 使用本技能,按“宜搭组件桥”接入并归一化值 |
|
|
42
42
|
| 需要字段结构、公式、联动、权限、报表、流程 | 使用对应配置型技能承载,Canvas 只做展示和事件分发 |
|
|
43
|
-
| 深度依赖普通页 `this` 实例桥 |
|
|
44
|
-
|
|
|
43
|
+
| 深度依赖普通页 `this` 实例桥 | 使用 `yida-custom-page` |
|
|
44
|
+
| 表单内字段双向绑定 `this.$(fieldId)`、`this.utils.yida.*`、`dataSourceMap`、提交流程深度耦合 | 使用 `yida-custom-page`(该实例桥由普通自定义页面提供) |
|
|
45
45
|
|
|
46
46
|
## 两类特殊组件场景
|
|
47
47
|
|
|
@@ -59,9 +59,9 @@ openyida sample yida-canvas-custom-page portal-native-components --output projec
|
|
|
59
59
|
|
|
60
60
|
- `PortalTopBanner`、`PortalQuickEntry`:优先接入,适合门户首页的 Banner 和快捷入口。
|
|
61
61
|
- `QuickAccessCard`、`RecentlyUsedCard`:先做运行态验证,再用于动态门户卡片。
|
|
62
|
-
- `DataCard`、`PortalContainer
|
|
62
|
+
- `DataCard`、`PortalContainer`:仅在目标门户上下文、数据卡片配置和样式变量都验证通过后启用。
|
|
63
63
|
|
|
64
|
-
做法:从 `window.Deep`、`window.DeepYida` 探测组件;若环境已有 `window.YidaNativeComponents`
|
|
64
|
+
做法:从 `window.Deep`、`window.DeepYida` 探测组件;若环境已有 `window.YidaNativeComponents` 也可兼容读取。探测到组件时渲染原生组件;未探测到时渲染 Canvas 自绘卡片,页面保持可用。
|
|
65
65
|
|
|
66
66
|
### 2. 成员、部门、上传组件
|
|
67
67
|
|
|
@@ -78,7 +78,7 @@ openyida sample yida-canvas-custom-page portal-native-components --output projec
|
|
|
78
78
|
- `DepartmentSelectField`:验证部门搜索、弹层、权限提示、单选/多选后启用。
|
|
79
79
|
- `AttachmentField` / `ImageField`:验证 OSS 签名、上传权限、预览、删除、失败提示后启用。
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
做法:原生组件负责交互输入;页面业务状态保存归一化后的成员、部门、文件结构;提交通过 fetch / 连接器 / 开放 API 完成。组件验证通过时使用原生组件;验证未通过时使用 Canvas 自绘输入、搜索或链接录入。
|
|
82
82
|
|
|
83
83
|
> 详细桥接规则、值结构和验收清单见 [native-components-bridge.md](references/native-components-bridge.md)。
|
|
84
84
|
|
|
@@ -88,35 +88,35 @@ openyida sample yida-canvas-custom-page portal-native-components --output projec
|
|
|
88
88
|
|
|
89
89
|
1. **Canvas 入口明确**:源码必须导出或返回 `YidaComp`,并把主组件作为默认导出或 `YidaComp` 暴露。
|
|
90
90
|
2. **发布链路正确**:Canvas 源码使用 `.canvas.jsx` / `.canvas.tsx`,或发布时显式加 `--canvas`。
|
|
91
|
-
3.
|
|
91
|
+
3. **源码修改发布闭环**:本轮 Write/Edit/Create 了 `project/pages/src/*.canvas.jsx` 或 `project/pages/src/*.canvas.tsx` 后,final 前需要成功执行 `openyida publish <source> <appType> <displayPageFormUuid>`。有 publish 成功证据时表述为“页面已发布”;只有本地校验证据时表述为“Canvas 源码已修改,尚未发布”。
|
|
92
92
|
4. **依赖可加载**:普通 import 只使用 Code Canvas 白名单依赖;宜搭运行态组件走原生组件桥。
|
|
93
|
-
5.
|
|
93
|
+
5. **使用 Canvas 函数组件契约**:Canvas 代码写 `YidaComp` React 函数组件;数据、生命周期和渲染都通过 hooks、props、fetch/连接器完成。需要 `renderJsx()`、`didMount()`、`this.forceUpdate()`、`this.utils.yida.*`、`this.dataSourceMap` 时切到 `yida-custom-page`。
|
|
94
94
|
6. **副作用清理**:`useEffect` 注册事件、定时器、图表实例时必须返回 cleanup。
|
|
95
|
-
7.
|
|
95
|
+
7. **交互控件必须受控且真正驱动数据**:筛选 `Select`、搜索 `Input`/`Input.Search`、周期切换、`Tabs`/`Segmented`、批量/重置 `Button` 等控件都用 `useState` 建立受控状态,绑定 `onChange`/`onClick`,并让 `Table`/列表/卡片的数据源通过 `useMemo` 按状态派生后渲染。切换筛选后若当前选中项失效,回退选中态(如 `selected < filteredRows.length ? selected : 0`)。
|
|
96
96
|
|
|
97
97
|
### 重要规则(IMPORTANT)
|
|
98
98
|
|
|
99
|
-
1. **数据桥显式化**:通过 fetch、连接器或开放 API
|
|
100
|
-
2.
|
|
101
|
-
3. **值先归一化**:成员、部门、文件的原始返回值只作为 `raw`
|
|
102
|
-
4. **业务页主色跟随应用主题,sample 例外**:真实业务页默认读取 `--color-brand1-*` 与 `--color-group
|
|
99
|
+
1. **数据桥显式化**:通过 fetch、连接器或开放 API 读写数据;Cookie、CSRF、密钥和签名留在平台、连接器或后端服务侧。
|
|
100
|
+
2. **组件增强可降级**:门户、成员、部门、上传组件都做 feature detect 和 fallback;组件缺失时页面仍展示 Canvas 自绘基线。
|
|
101
|
+
3. **值先归一化**:成员、部门、文件的原始返回值只作为 `raw` 检查信息,业务 payload 使用统一结构。
|
|
102
|
+
4. **业务页主色跟随应用主题,sample 例外**:真实业务页默认读取 `--color-brand1-*` 与 `--color-group`;`lib/samples/**` 和官方 sample 展示应用自带页面级固定主题(`followRuntimeTheme: false` 或等价 CSS 变量),每个 sample 使用不同色相。
|
|
103
103
|
5. **先验证再扩展业务**:原生组件、上传、组织搜索、弹层类能力先做 smoke 页面,确认 PC/移动端都可用后再承载复杂业务。
|
|
104
|
-
6. **模板占位符必须可直发**:Canvas sample / generate-page
|
|
105
|
-
7. **light
|
|
106
|
-
8. **门户运行态组件要补必需 props 和局部降级**:`QuickAccessCard` / `RecentlyUsedCard`
|
|
107
|
-
9. **自定义主题必须页面内注入**:`--theme` 只接受平台预置 key
|
|
108
|
-
10.
|
|
109
|
-
11.
|
|
110
|
-
12. **Canvas
|
|
104
|
+
6. **模板占位符必须可直发**:Canvas sample / generate-page 模板同时支持“生成器替换变量”和“sample 原样发布”。JSON 占位符用 `parseTemplateJson(raw, fallback)`,展示文案占位符用 `withFallback` / `applyPageFallbacks` 兜底,未替换时页面继续可运行,并显示业务化 fallback 文案。
|
|
105
|
+
7. **light 页面使用清爽业务色**:业务列表、协同表、数据管理页、工作台和门户默认使用 light 模式;主操作、选中态、筛选焦点和批量操作使用品牌色或 sample 自带主题色,边框用浅色品牌混合。用户明确要求暗色大屏/夜间模式/高对比风格时使用深色主视觉。
|
|
106
|
+
8. **门户运行态组件要补必需 props 和局部降级**:`QuickAccessCard` / `RecentlyUsedCard` 传 `theme="row-white"` 等必需 props;所有门户/字段/上传增强组件外层加局部 ErrorBoundary,单个组件不兼容时只降级该块,整页保持可用。
|
|
107
|
+
9. **自定义主题必须页面内注入**:`--theme` 只接受平台预置 key;页面设计使用非预置主题(例如活力橙、深玫红、自定义暗黑金)时,在 Canvas 源码中注入 `style#yida-global-theme` 或等价 scoped CSS vars,并在根节点设置 `data-theme-scope="page"`。官方 sample 每个页面都做页面级主题注入。
|
|
108
|
+
10. **真实交付使用真实数据源**:`openyida sample` 原样发布可以保留 sample/seed 数据,并在页面上标注为 sample/seed。完整应用或真实交付页只要需要列表、看板、详情记录,并且本轮已经创建/解析业务表单,就在 `page-spec.json` 写入 `dataBinding.mode=form`、真实 `appType/formUuid` 和字段映射,让页面从表单读取。需要演示数据时,先通过表单数据写入链路创建 demo/mock records,再由 Canvas 读取这些真实表单记录;没有真实数据时展示空态、表单入口、刷新/登记按钮。
|
|
109
|
+
11. **页面生成二选一**:模板路径先写 `page-spec.json`,执行 `openyida generate-page ... --spec ... --compile`,之后读取 CLI 摘要或 `.openyida-page.json` 判断 `domainFidelity` / dataBinding,并对生成源码做小范围 Edit/patch。手写路径直接 Write 最终 `.canvas.jsx` 并快检/发布。
|
|
110
|
+
12. **Canvas 产物使用纯文本业务文案**:`.canvas.jsx` 源码、模板 spec 会渲染到页面的文案、JS 注释、数据常量和产物文件路径都使用无 emoji 文本。`generate-page --compile`、`compileCanvasLocal` 或 `publish` 报 emoji 错误时,先改 spec/源码/路径,再重新校验发布。
|
|
111
111
|
|
|
112
112
|
## 数据真实性边界
|
|
113
113
|
|
|
114
114
|
Canvas 模板有两种允许状态:
|
|
115
115
|
|
|
116
116
|
- **Sample / 离线预览**:`openyida sample` 或模板原样发布可以显示内置 seedRows,页面必须标注 `sample/seed`,final 也要说明“当前为演示数据/未接真实表单数据”。
|
|
117
|
-
- **完整应用 / 真实交付**:先解析真实 `appType/formUuid/fieldId`,写入 `page-spec.json` 的 `dataBinding.mode=form` 后再 `openyida generate-page ... --spec <page-spec.json>`。需要 demo/mock
|
|
117
|
+
- **完整应用 / 真实交付**:先解析真实 `appType/formUuid/fieldId`,写入 `page-spec.json` 的 `dataBinding.mode=form` 后再 `openyida generate-page ... --spec <page-spec.json>`。需要 demo/mock 记录时,先用数据写入链路把记录写入表单并抽查,再让页面读取;前端 seedRows、静态 DEFAULT_FEATURES 或固定指标只作为 sample 数据标注。
|
|
118
118
|
|
|
119
|
-
生成后如果 `.openyida-page.json` 的 `dataBinding.enabled !== true
|
|
119
|
+
生成后如果 `.openyida-page.json` 的 `dataBinding.enabled !== true`,且页面仍展示列表/看板/详情业务记录,交付状态标为 sample/draft;完整应用 final 只有在真实数据绑定已启用并验证后表述为“已接真实数据”。未接数据的交付页保留真实空态、登记入口、刷新按钮和数据接入提示。
|
|
120
120
|
|
|
121
121
|
## 模板占位符防回归
|
|
122
122
|
|
|
@@ -128,9 +128,9 @@ Canvas 模板有两条真实使用链路:
|
|
|
128
128
|
因此模板源码必须满足:
|
|
129
129
|
|
|
130
130
|
- 原始 sample 经过 `compileCanvasLocal` 能通过。
|
|
131
|
-
- 原始 sample 执行 `YidaComp()`
|
|
132
|
-
-
|
|
133
|
-
-
|
|
131
|
+
- 原始 sample 执行 `YidaComp()` 能正常返回组件。
|
|
132
|
+
- 可见渲染内容显示业务化文案或 fallback 文案。
|
|
133
|
+
- JSON 占位符使用安全解析函数接默认数据。
|
|
134
134
|
|
|
135
135
|
改 Canvas sample 后运行:
|
|
136
136
|
|
|
@@ -138,27 +138,26 @@ Canvas 模板有两条真实使用链路:
|
|
|
138
138
|
npx jest tests/canvas-compile.test.js tests/generate-page.test.js --runInBand
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
## Sample
|
|
141
|
+
## Sample 质量规则
|
|
142
142
|
|
|
143
|
-
批量优化 `lib/samples/**` 或官方 sample
|
|
143
|
+
批量优化 `lib/samples/**` 或官方 sample 展示应用时,按以下质量规则执行:
|
|
144
144
|
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
- **说清参考转译**:交付 sample 改造时要用 1-2 句话说明参考被转译成了什么,例如“详情页采用对象 hero + sticky 元信息 + 时间线结构”、“数据管理页采用多维表工具栏 + 分组行 + 彩色标签密集表格”。不要只说“已参考 Dribbble”。
|
|
145
|
+
- **先看参考再动手**:用户要求“高级、Dribbble、好看、像产品/官网/详情页/数据表”时,先参考 Dribbble 的同类构图和免费可商用素材站的真实图片,再抽象成布局、层次、色彩和数据密度原则,并转译为当前业务页面。
|
|
146
|
+
- **说清参考转译**:交付 sample 改造时要用 1-2 句话说明参考被转译成了什么,例如“详情页采用对象 hero + sticky 元信息 + 时间线结构”、“数据管理页采用多维表工具栏 + 分组行 + 彩色标签密集表格”。
|
|
148
147
|
- **每页独立主题**:sample 页默认 `themeScope=page` 或等价固定 CSS 变量;业务列表、详情、门户、工作台、官网、数据管理、大屏要有不同色相和不同信息节奏,不被宿主应用主题统一染色。
|
|
149
148
|
- **非预置主题不走 `--theme`**:`deepBlue/podBlue/.../black` 这些平台 key 才能传给 `--theme`;自己设计的主题色要写到页面 `style#yida-global-theme` / scoped token 中,并确保每个 sample 页面都有这段注入。
|
|
150
|
-
- **Sample
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
155
|
-
- **交互要真的联动数据**:改完带筛选/搜索/切换的 sample
|
|
149
|
+
- **Sample 数据要像真实业务,真实交付要接真实数据**:列表、详情、数据管理、工作台、大屏 sample 模拟足够丰富的数据、状态、筛选、趋势、分组、时间线或指标;完整应用/真实交付页优先接 `dataBinding.mode=form`,未接入时展示真实空态。
|
|
150
|
+
- **工作台使用真实产品首页结构**:工作台页面铺满应用内容区,侧栏/导航/主面板形成真实产品首页;设计过程词不出现在可见页面。
|
|
151
|
+
- **数据大屏地图要稳定**:大屏中心态势图如果是地图,优先探测宜搭宿主地图组件(如 `YoushuMap` / `ChinaMap` / `MapChart` 等),并提供内置区域地图组件兜底;正常展示态呈现地图、区域态势或业务空态。
|
|
152
|
+
- **截图验收要覆盖模板共性**:导航覆盖、地图表现、配色、内容丰富度、产品首页结构等属于模板共性时,同步补 sample 模板、测试或本技能规则。
|
|
153
|
+
- **官网实景化覆盖完整品牌旅程**:强视觉官网至少形成“场景 Hero + 产品/服务 + 过程/空间”的摄影故事,品牌色从真实材质提取,section 覆盖真实产品、制作/服务过程与到店/使用情境。具体按 `yida-page-uiux/references/landing/realistic-brand-homepage.md` 执行。
|
|
154
|
+
- **交互要真的联动数据**:改完带筛选/搜索/切换的 sample,实际验证“改筛选 → 下方列表/表格/卡片数据发生变化”。控件使用受控状态、`onChange`/`onClick` 和派生数据源。
|
|
156
155
|
- **线上发布后回读**:发布到官方 sample 应用后,用 `get-schema` 回读确认 `YidaCodeCanvas/runtimeCode` 已更新,必要时检查页面 class/关键文案/关键区块存在。
|
|
157
|
-
- **CLI
|
|
156
|
+
- **CLI 能力缺口要补齐**:sample 注册、模板类型、发布生效、测试覆盖等 CLI 共性缺口优先补 CLI/测试。
|
|
158
157
|
|
|
159
158
|
## 开发流程
|
|
160
159
|
|
|
161
|
-
下面命令以仓库根为视角;如果当前 cwd 已经是 `<workspace>/project`,把 `project/pages/src/...` 改成 `pages/src/...`。读取生成文件、Schema 或校验产物时优先用宿主 Read / Glob / Grep
|
|
160
|
+
下面命令以仓库根为视角;如果当前 cwd 已经是 `<workspace>/project`,把 `project/pages/src/...` 改成 `pages/src/...`。读取生成文件、Schema 或校验产物时优先用宿主 Read / Glob / Grep。
|
|
162
161
|
|
|
163
162
|
```bash
|
|
164
163
|
# 1. 只读检查环境和登录态;真实创建资源前必须通过
|
|
@@ -187,9 +186,9 @@ openyida publish project/pages/src/<页面名>.canvas.jsx <appType> <formUuid>
|
|
|
187
186
|
openyida get-schema <appType> <formUuid> --field-map-json
|
|
188
187
|
```
|
|
189
188
|
|
|
190
|
-
`openyida check-page` / `openyida compile` 当前面向普通自定义页面 `.oyd.jsx` / `.jsx`;Canvas 以 `compileCanvasLocal` 和 `openyida publish .canvas.jsx` 的 Canvas 编译阶段为准。`compileCanvasLocal`
|
|
189
|
+
`openyida check-page` / `openyida compile` 当前面向普通自定义页面 `.oyd.jsx` / `.jsx`;Canvas 以 `compileCanvasLocal` 和 `openyida publish .canvas.jsx` 的 Canvas 编译阶段为准。`compileCanvasLocal` 是发布前快检,`openyida publish` 是远端写入证据。
|
|
191
190
|
|
|
192
|
-
如需保存完整 Schema,使用 create_file / Write / file edit tool 创建 `<projectRoot>/.cache/openyida/<页面名或任务名>/<页面名>-schema.json`;从 workspace 根执行后续命令时路径加 `project/`
|
|
191
|
+
如需保存完整 Schema,使用 create_file / Write / file edit tool 创建 `<projectRoot>/.cache/openyida/<页面名或任务名>/<页面名>-schema.json`;从 workspace 根执行后续命令时路径加 `project/` 前缀。
|
|
193
192
|
|
|
194
193
|
## 模板速查
|
|
195
194
|
|
|
@@ -211,11 +210,10 @@ openyida get-schema <appType> <formUuid> --field-map-json
|
|
|
211
210
|
| --- | --- | --- |
|
|
212
211
|
| [page-generation-guide.md](references/page-generation-guide.md) | 模板路由、官网素材、themeScope、Page Spec、primitives | 生成页面前必读 |
|
|
213
212
|
| [native-components-bridge.md](references/native-components-bridge.md) | 门户、成员、部门、上传组件桥接和值归一化 | 需要宜搭运行态组件时必读 |
|
|
214
|
-
| [dependencies-and-cdn.md](references/dependencies-and-cdn.md) | 依赖白名单、windowAlias、CDN
|
|
213
|
+
| [dependencies-and-cdn.md](references/dependencies-and-cdn.md) | 依赖白名单、windowAlias、CDN 加载契约 | 新增依赖或验证依赖加载时必读 |
|
|
215
214
|
| [employeefield-verification.md](references/employeefield-verification.md) | 运行时事实、原生组件验证、EmployeeField 验收 | 验证成员/字段组件时阅读 |
|
|
216
215
|
| [data-bridge-guide.md](references/data-bridge-guide.md) | Canvas 内自建 HTTP 数据桥 | 接入真实数据时阅读 |
|
|
217
216
|
| [canvas-design-system.md](references/canvas-design-system.md) | App 主题色、antd token、控件焦点/下拉 reset、图表配色 | 写样式和主题时阅读 |
|
|
218
217
|
| [component-library-guide.md](references/component-library-guide.md) | 开源组件库推荐组合和禁用清单 | 选择 UI/图表依赖时阅读 |
|
|
219
218
|
| [canvas-authoring-examples.md](references/canvas-authoring-examples.md) | 最小组件、hooks、副作用、图表示例 | 手写 Canvas 代码时阅读 |
|
|
220
219
|
| [真实品牌官网 Playbook](../yida-page-uiux/references/landing/realistic-brand-homepage.md) | 实景素材组、材质配色、品牌旅程、Sample 无 CDN 兜底和视觉验收 | 生成或改造强视觉官网时必读 |
|
|
221
|
-
| [任务复盘与沉淀规范](../../references/task-retrospective.md) | 官方 sample 改造经验、Dribbble 转译、页面级主题、发布回读、CLI/skill 反哺 | sample 批量优化、截图纠错、用户要求总结经验时阅读 |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
本文件是从零写 Code Canvas 页面的 vetted 模板集。所有示例都遵守运行时事实:`YidaComp` 是普通 React18 函数组件,必须**导出或返回** `YidaComp` / `YidaComp.default`;只 `import` 依赖白名单内的包;副作用在 `useEffect` 里注册并返回 cleanup。
|
|
4
4
|
|
|
5
|
-
> 白名单、windowAlias
|
|
5
|
+
> 白名单、windowAlias 与 CDN 加载契约见 [dependencies-and-cdn.md](dependencies-and-cdn.md);读写宜搭数据见 [data-bridge-guide.md](data-bridge-guide.md)。
|
|
6
6
|
|
|
7
7
|
## 1. 最小可运行组件(入口 + 本地状态)
|
|
8
8
|
|
|
@@ -60,7 +60,7 @@ export default YidaComp;
|
|
|
60
60
|
|
|
61
61
|
## 3. 可视化:recharts 图表
|
|
62
62
|
|
|
63
|
-
`recharts` 在白名单内(windowAlias `Recharts`)。标准 `import` 即可,CLI 本地编译会把它计入 `importedModules
|
|
63
|
+
`recharts` 在白名单内(windowAlias `Recharts`)。标准 `import` 即可,CLI 本地编译会把它计入 `importedModules`。图表容器给定高度,保证首屏可渲染。图表颜色是 JS 传给库的字符串,用 `readBrandColor` 读平台品牌色,让线条跟随 App 主题(见 [canvas-design-system.md](canvas-design-system.md))。
|
|
64
64
|
|
|
65
65
|
```jsx
|
|
66
66
|
import React from 'react';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Code Canvas 主色对齐与视觉落地
|
|
2
2
|
|
|
3
|
-
本文件是 Code Canvas
|
|
3
|
+
本文件是 Code Canvas 页面的**实现层**引导:真实业务页跟随宿主 App 的品牌主题色;官方 sample / 示例展示应用自带页面级固定主题和差异化色盘。视觉方向(页面类型、差异化、去 AI 味)走共用的决策层技能 `yida-page-uiux`,本文件只讲 Canvas(React18 + antd + Tailwind)这套栈怎么把主色落地。
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> 决策层:需要视觉方向时先遵循 `yida-page-uiux` 技能(先做 Step 0 导航形态判定,再定工作台/仪表盘/列表/详情、5 维差异化、去 AI 味、禁 emoji)。
|
|
6
6
|
> 实现层:本文件负责把「真实业务页主色跟随 App 品牌」和「sample 页面级独立主题」落到 antd token / Tailwind / 图表。
|
|
7
7
|
|
|
8
|
-
>
|
|
8
|
+
> **前提是导航可见且是真实业务页**:跟随品牌主色是为了跟应用框架融合。页面隐藏应用导航(`isRenderNav=false`,沉浸/独立/门户/大屏,由 `yida-page-uiux` Step 0 判定)时,主色相可自立。`lib/samples/**` 或官方 sample 展示应用也使用自立主色相:`followRuntimeTheme: false`,antd `colorPrimary` / 图表色 / CSS 变量都喂页面自己的固定色盘,语义色保持固定。
|
|
9
9
|
|
|
10
10
|
## themeScope:页面级与应用级换肤
|
|
11
11
|
|
|
@@ -63,11 +63,11 @@ React.useEffect(function () {
|
|
|
63
63
|
}, []);
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
命令侧:`openyida generate-page product-homepage --theme-profile yida-app-theme --theme-scope page|app --compile
|
|
66
|
+
命令侧:`openyida generate-page product-homepage --theme-profile yida-app-theme --theme-scope page|app --compile`。页面级换肤写 scoped 变量;应用级换肤使用显式 `themeScope: app`。
|
|
67
67
|
|
|
68
68
|
## 自然语言推断规则
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
按用户自然语言直接推断 `themeScope` 并写入 spec:
|
|
71
71
|
|
|
72
72
|
| 用户说法 | spec |
|
|
73
73
|
| --- | --- |
|
|
@@ -78,7 +78,7 @@ Agent 不应要求用户说出 `themeScope`。当用户表达以下含义时,
|
|
|
78
78
|
|
|
79
79
|
同一句话同时出现“整体应用”和“不要影响导航”这类冲突时,以限制更强的 `page` 为准,或者简短确认一次。
|
|
80
80
|
|
|
81
|
-
## 核心事实:CSS
|
|
81
|
+
## 核心事实:CSS 变量直接级联,antd token 使用解析色值
|
|
82
82
|
|
|
83
83
|
Canvas 的 `runtimeCode` 在**宿主页真实 `window`** 里 `new Function` 执行(见 SKILL.md「运行时事实」),组件挂在宿主 DOM 树内。由此得到主色落地的分界:
|
|
84
84
|
|
|
@@ -113,7 +113,7 @@ function useBrandColor(level, fallback) {
|
|
|
113
113
|
}
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
>
|
|
116
|
+
> **变量作用域**:平台把 `--color-brand1-*` 定义在页面容器时,给组件根节点挂 `ref`,在 `useEffect` 里读 `getComputedStyle(rootRef.current)`,读到后 `setState` 触发一次重渲染。默认先用 `documentElement` 同步取值,空串时再用根节点 ref 读取。
|
|
117
117
|
|
|
118
118
|
## antd:ConfigProvider 注入 colorPrimary
|
|
119
119
|
|
|
@@ -157,17 +157,17 @@ export default YidaComp;
|
|
|
157
157
|
|
|
158
158
|
## 默认 light 模式避免灰黑主题
|
|
159
159
|
|
|
160
|
-
业务列表、协同表、数据管理页、工作台和门户默认都是 light
|
|
160
|
+
业务列表、协同表、数据管理页、工作台和门户默认都是 light 模式。正文使用深色保证可读性;主操作、选中态、筛选焦点、批量操作和信息标签使用品牌色或 sample 自带主题色;卡片边框、表格分割线和下拉浮层边框使用浅色品牌混合,例如 `#DCE6F2`、`color-mix(in srgb, var(--oy-brand) 16%, #DDE8F4)`。用户明确要求暗色大屏、夜间模式或高对比风格时使用深色主视觉。
|
|
161
161
|
|
|
162
162
|
## 控件焦点态与下拉浮层 reset
|
|
163
163
|
|
|
164
|
-
Code Canvas
|
|
164
|
+
Code Canvas 页面只要出现搜索框、筛选下拉、日期选择、文本输入、成员/部门/上传等运行态控件,就在页面 `<style>` 顶部注入控件 reset,统一输入框、下拉触发器、focus ring 和字体粗细。
|
|
165
165
|
|
|
166
166
|
实现规则:
|
|
167
167
|
|
|
168
168
|
- `ConfigProvider` 增加 `getPopupContainer={(triggerNode) => (triggerNode && triggerNode.parentElement) || document.body}`,让 antd Select / DatePicker 等弹层留在当前页面作用域,避免浮层脱离页面样式。
|
|
169
169
|
- 页面根节点使用 `oy-*` 根类,并在 `<style>` 顶部放 `OPENYIDA_CANVAS_CONTROL_CSS` 同款 reset。
|
|
170
|
-
- 控件默认边框使用浅灰蓝,hover 使用品牌色低饱和混合,focus 使用浅品牌描边 + 3px 柔和 ring
|
|
170
|
+
- 控件默认边框使用浅灰蓝,hover 使用品牌色低饱和混合,focus 使用浅品牌描边 + 3px 柔和 ring。
|
|
171
171
|
- 下拉浮层统一 10px 圆角、浅边框、柔和阴影,active / selected 选项使用品牌浅底,不用黑色描边或浏览器原生 select。
|
|
172
172
|
|
|
173
173
|
最小片段:
|
|
@@ -221,7 +221,7 @@ Canvas 节点在宿主树内,Tailwind 运行时对普通元素直接用 arbitr
|
|
|
221
221
|
|
|
222
222
|
## 图表 / recharts:用解析后的品牌色组
|
|
223
223
|
|
|
224
|
-
图表颜色是 JS
|
|
224
|
+
图表颜色是 JS 传给库的字符串,使用 `readBrandColor` 或解析 `--color-group`。多系列图表优先读 `--color-group`,这样应用主题里的色组可以控制趋势线、柱状、排名和环形图的层次。
|
|
225
225
|
|
|
226
226
|
```jsx
|
|
227
227
|
import React from 'react';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Code Canvas 开源组件库选型
|
|
2
2
|
|
|
3
|
-
本文件回答「Code Canvas
|
|
3
|
+
本文件回答「Code Canvas 还能用哪些开源组件库」以及生成页面时该怎么选。结论先行:页面默认使用已经在 Code Canvas 依赖白名单内、且 OpenYida 本地编译能映射到 windowAlias 的库;白名单外能力先走 Canvas 自绘、连接器、运行态组件桥或新增依赖评审。
|
|
4
4
|
|
|
5
5
|
依赖白名单、版本和 windowAlias 以 [dependencies-and-cdn.md](dependencies-and-cdn.md) 为准;本文件只做产品化选型建议。
|
|
6
6
|
|
|
@@ -8,20 +8,20 @@
|
|
|
8
8
|
|
|
9
9
|
| 场景 | 推荐库 | 何时使用 | 注意事项 |
|
|
10
10
|
| --- | --- | --- | --- |
|
|
11
|
-
| B 端业务界面 | `antd` | 表格、表单控件、按钮、弹窗、Tabs、Tag、Dropdown、分页 | 最外层包 `ConfigProvider`,主色用 `readBrandColor`
|
|
11
|
+
| B 端业务界面 | `antd` | 表格、表单控件、按钮、弹窗、Tabs、Tag、Dropdown、分页 | 最外层包 `ConfigProvider`,主色用 `readBrandColor` 注入;按白名单 import,不自行注入依赖脚本 |
|
|
12
12
|
| 图表看板 | `recharts` | 折线、柱状、面积、饼图、简单仪表盘 | 容器必须有稳定高度;颜色用品牌色和语义色,不硬编码默认蓝 |
|
|
13
13
|
| 复杂可视化 | `d3` | 自定义关系图、力导向、桑基、特殊坐标系 | 只在 Recharts 覆盖不了时使用;自己管理 DOM/cleanup |
|
|
14
|
-
| 图标 | 内联 SVG 语义集 | 按钮、操作、状态、导航等功能性图标 |
|
|
15
|
-
| 交互动效 | `framer-motion` | 抽屉、轻量过渡、局部状态切换 | B
|
|
16
|
-
| Hooks 工具 | `ahooks` | 防抖、请求状态、定时器、列表状态等 |
|
|
14
|
+
| 图标 | 内联 SVG 语义集 | 按钮、操作、状态、导航等功能性图标 | 默认选择,零依赖且不会出现运行时组件 undefined |
|
|
15
|
+
| 交互动效 | `framer-motion` | 抽屉、轻量过渡、局部状态切换 | B 端页面使用克制、局部、服务状态理解的动效 |
|
|
16
|
+
| Hooks 工具 | `ahooks` | 防抖、请求状态、定时器、列表状态等 | 用来简化状态逻辑;数据读写仍走明确数据桥 |
|
|
17
17
|
| 轻量主题组件 | `@radix-ui/themes` | 需要更原子化、更少 antd 味的按钮、卡片、布局控件 | 与 antd 混用时要统一圆角、字体、色彩和弹层层级 |
|
|
18
|
-
| Markdown 展示 | `yida-plugin-markdown` | PRD、公告、帮助文档、AI 输出内容展示 |
|
|
18
|
+
| Markdown 展示 | `yida-plugin-markdown` | PRD、公告、帮助文档、AI 输出内容展示 | 用于展示可信 Markdown 内容;用户输入内容先清洗再展示 |
|
|
19
19
|
|
|
20
20
|
## 默认选型规则
|
|
21
21
|
|
|
22
22
|
1. **普通业务页默认 `antd + ahooks + 内联 SVG 图标`**:这是最稳的 B 端组合,适合列表、工作台、详情、审批辅助页。
|
|
23
23
|
2. **看板默认 `antd + recharts + ahooks + 内联 SVG 图标`**:KPI、筛选、图表和明细表都能覆盖;只有 Recharts 做不了的图才引入 `d3`。
|
|
24
|
-
3. **需要去 antd 味时,少量使用 `@radix-ui/themes
|
|
24
|
+
3. **需要去 antd 味时,少量使用 `@radix-ui/themes`**:适合展示页、门户页、较轻的工具页;同一页面选一个主视觉语言,另一套组件只做局部补充。
|
|
25
25
|
4. **动效只作为状态反馈**:`framer-motion` 用在抽屉、折叠、局部切换,不用于整页炫酷入场。
|
|
26
26
|
5. **图标只作功能用途**:默认内联 SVG;`lucide-react` 只有在当前租户环境最小验证通过后才可使用,不进入默认模板。
|
|
27
27
|
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
|
|
30
30
|
`lucide-react` 在依赖白名单内,但不同运行时打包形态可能只暴露 `window.DynamicIcon`,不一定稳定提供 `RefreshCw`、`TrendingUp` 等 named exports。若页面直接写 `<RefreshCw />` 而运行时该导出为 `undefined`,React 会报 `Minified React error #130`。
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
因此默认模板使用内联 SVG 图标。需要使用 `lucide-react` 时先创建最小验证页,确认目标图标组件确实存在;验证前沿用内联 SVG。
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## 需要扩展白名单后使用
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
以下库属于常见开源选择,但当前 Code Canvas 白名单未承诺加载。页面先使用上文推荐组合;确需使用这些库时,先完成依赖扩展和运行时验证:
|
|
37
37
|
|
|
38
38
|
- `@mui/material` / MUI
|
|
39
39
|
- `@mantine/core`
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
- `echarts`(普通自定义页面可通过 `loadScript` 用 ECharts;Canvas 当前白名单优先用 `recharts` / `d3`)
|
|
44
44
|
- 任意未在 [dependencies-and-cdn.md](dependencies-and-cdn.md) 出现的 npm 包
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
新增库需要补齐三件事:OpenYida `canvas-compile.js` 的 alias 映射、Code Canvas 物料运行时依赖白名单和 CDN 资源、样式资源加载验证。三项都完成后,再进入生成默认推荐。
|
|
47
47
|
|
|
48
48
|
## 生成页面时的组合示例
|
|
49
49
|
|
|
@@ -64,7 +64,7 @@ node -e "const fs=require('fs'); const {compileCanvasLocal}=require('./lib/app/c
|
|
|
64
64
|
## 自查清单
|
|
65
65
|
|
|
66
66
|
- 所有 `import` 都在白名单内,并能出现在 `importedModules`。
|
|
67
|
-
- 页面视觉方向已经先走 `yida-page-uiux
|
|
67
|
+
- 页面视觉方向已经先走 `yida-page-uiux`,组件库服务于既定视觉方向。
|
|
68
68
|
- antd 主色通过 `ConfigProvider` 跟随 App 品牌色。
|
|
69
|
-
-
|
|
70
|
-
-
|
|
69
|
+
- 图表和图标服务于信息层级;图标默认内联 SVG,`lucide-react` 通过最小验证后再启用。
|
|
70
|
+
- 默认模板、示例和推荐话术只包含当前已验证白名单能力。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Code Canvas 数据桥指南(自写 HTTP 读写宜搭数据)
|
|
2
2
|
|
|
3
|
-
Code Canvas 运行时**没有** `this.utils.yida.*` / `dataSourceMap` / `this.$(fieldId)`
|
|
3
|
+
Code Canvas 运行时**没有** `this.utils.yida.*` / `dataSourceMap` / `this.$(fieldId)` 实例数据桥;`YidaComp` 是普通 React 函数组件。因此 `YidaComp` 要读写宜搭数据,只能在组件内使用 HTTP 数据桥、连接器代理或显式 props 注入。本文件给出干净、可复用、合规的写法。
|
|
4
4
|
|
|
5
5
|
## 三条数据路径,先选对
|
|
6
6
|
|
|
@@ -8,9 +8,9 @@ Code Canvas 运行时**没有** `this.utils.yida.*` / `dataSourceMap` / `this.$(
|
|
|
8
8
|
| --- | --- | --- |
|
|
9
9
|
| 宜搭开放 API(OpenAPI,`appKey`/`appSecret` 签名) | **不可** | 需服务端签名;在浏览器里必然泄露 secret。只能由后端 / 连接器代理调,Canvas 不直连。 |
|
|
10
10
|
| 平台已配置**连接器**(HTTP 连接器暴露的同源代理端点) | **推荐** | 同源 `fetch(url, { credentials: 'include' })` 带 cookie 即可,鉴权与密钥留在平台侧,符合数据源治理。 |
|
|
11
|
-
| 内部表单数据端点(同源、依赖登录 cookie + CSRF) | 可,但要谨慎 | 与普通自定义页面 `this.utils.yida.searchFormDatas`
|
|
11
|
+
| 内部表单数据端点(同源、依赖登录 cookie + CSRF) | 可,但要谨慎 | 与普通自定义页面 `this.utils.yida.searchFormDatas` 命中的是同类端点;使用同源相对路径、`credentials: 'include'` 和运行态 CSRF token。 |
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
选路原则:优先走连接器代理,让鉴权、密钥和数据源治理留在平台侧。真需要直连内部端点时,使用**同源相对路径** + `credentials: 'include'`,Cookie / CSRF / appSecret 由平台上下文或后端服务提供。
|
|
14
14
|
|
|
15
15
|
## 推荐:先写 dataBinding,再生成数据桥
|
|
16
16
|
|
|
@@ -39,10 +39,10 @@ OpenYida `generate-page --spec` 支持把 Canvas 数据契约写成结构化 `da
|
|
|
39
39
|
|
|
40
40
|
数据绑定规则:
|
|
41
41
|
|
|
42
|
-
- `mode=form`
|
|
43
|
-
- `mode=connector/url`
|
|
44
|
-
- `mode=seed`
|
|
45
|
-
- 模板生成的 `DataBridge`
|
|
42
|
+
- `mode=form` 使用真实 `appType/formUuid` 和字段 ID,字段来源为 `get-schema`、表单创建结果或已确认的业务 Schema。
|
|
43
|
+
- `mode=connector/url` 使用同源代理端点,第三方密钥留在连接器或后端服务侧。
|
|
44
|
+
- `mode=seed` 用于 `openyida sample`、离线预览或明确标注的演示页;完整应用/真实交付页需要演示记录时,先把 demo/mock records 写入真实表单,再用 `mode=form` 读取。
|
|
45
|
+
- 模板生成的 `DataBridge` 状态要保留,用于呈现“接口没通 / 结构没识别 / 权限不足”等运行时状态。
|
|
46
46
|
|
|
47
47
|
## 可复用读数据 Hook
|
|
48
48
|
|
|
@@ -125,14 +125,14 @@ function useYidaFetch(buildRequest, deps) {
|
|
|
125
125
|
|
|
126
126
|
要点:
|
|
127
127
|
|
|
128
|
-
- `credentials: 'include'`
|
|
129
|
-
- 如需 CSRF,优先从 `window.g_config._csrf_token` / `window.g_config.csrfToken` 动态读取,按接口要求放入 `_csrf_token` 请求参数和 / 或 `global_csrf_token`
|
|
128
|
+
- `credentials: 'include'` 让浏览器带上同源登录态;Cookie 由浏览器和平台管理。
|
|
129
|
+
- 如需 CSRF,优先从 `window.g_config._csrf_token` / `window.g_config.csrfToken` 动态读取,按接口要求放入 `_csrf_token` 请求参数和 / 或 `global_csrf_token` 头。
|
|
130
130
|
- 用 `AbortController` 在卸载 / 依赖变化时取消,避免 setState-after-unmount(对应编码规则 #5 副作用清理)。
|
|
131
|
-
-
|
|
131
|
+
- 解析响应按**真实返回结构**处理;不同端点和运行态会出现 `data`、`result.data`、`content.data`、`content.result.data`、`list`、`values`、`records` 等包装。
|
|
132
132
|
|
|
133
133
|
## 表单查询返回体必须递归解析
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
“数据管理里有数据,但 Code Canvas 页面显示 0 条”的常见失败模式是响应体被多层包装,页面只读了错误层级。统一使用下面的解析器,既兼容数组位置,也能在 `totalCount > 0` 但解析为 0 条时主动暴露故障。
|
|
136
136
|
|
|
137
137
|
```jsx
|
|
138
138
|
function unwrapRows(payload) {
|
|
@@ -194,8 +194,8 @@ function normalizeFormRow(row) {
|
|
|
194
194
|
|
|
195
195
|
保护规则:
|
|
196
196
|
|
|
197
|
-
- 首屏只有 sample/离线预览可以用 seed
|
|
198
|
-
- 如果 `getTotalCount(json) > 0` 且 `unwrapRows(json).length === 0
|
|
197
|
+
- 首屏只有 sample/离线预览可以用 seed 数据做本地预览兜底;真实交付页未接表单数据时展示空态和登记入口。真实接口返回后以接口数据为准。
|
|
198
|
+
- 如果 `getTotalCount(json) > 0` 且 `unwrapRows(json).length === 0`,展示“接口返回结构未识别”,并保留原始错误状态供定位。
|
|
199
199
|
- 用 `openyida data query form <appType> <formUuid> --size 20` 或数据管理页核对总数,页面统计必须和真实表单一致。
|
|
200
200
|
|
|
201
201
|
## 在组件里用
|
|
@@ -239,7 +239,7 @@ export default YidaComp;
|
|
|
239
239
|
|
|
240
240
|
## 轮询只刷新数据,不刷新整页
|
|
241
241
|
|
|
242
|
-
多人同时提交、点赞、更新状态的留言板 / 投票墙 /
|
|
242
|
+
多人同时提交、点赞、更新状态的留言板 / 投票墙 / 任务看板,需要轮询让不同用户看到同一份状态。轮询更新统计和列表,保留当前页面和已加载数据状态。
|
|
243
243
|
|
|
244
244
|
```jsx
|
|
245
245
|
var POLL_INTERVAL_MS = 5000;
|
|
@@ -263,7 +263,7 @@ function YidaComp() {
|
|
|
263
263
|
setLoading(true);
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
//
|
|
266
|
+
// 直连 searchFormDatas.json 必须 GET + query(见下文请求契约):
|
|
267
267
|
// formUuid/appType 放 URL query,分页参数名是 currentPage(不是 pageNumber)。
|
|
268
268
|
var qs = new URLSearchParams({
|
|
269
269
|
formUuid: '<FORM_UUID>',
|
|
@@ -307,18 +307,18 @@ function YidaComp() {
|
|
|
307
307
|
}
|
|
308
308
|
```
|
|
309
309
|
|
|
310
|
-
|
|
310
|
+
排序也要按用户语义明确:页面是“最新建议”时,按 `gmtCreate` / 提交日期倒序;页面是“排行榜”时,先按点赞数倒序,再用创建时间做 tie-break。验收时同时看总数和排序规则,确认新增记录是否进入正确位置。
|
|
311
311
|
|
|
312
|
-
## 直连内部端点 `searchFormDatas.json`
|
|
312
|
+
## 直连内部端点 `searchFormDatas.json` 请求契约
|
|
313
313
|
|
|
314
|
-
不方便配连接器、只需读本应用表单数据时,可同源直连内部端点 `searchFormDatas.json
|
|
314
|
+
不方便配连接器、只需读本应用表单数据时,可同源直连内部端点 `searchFormDatas.json`。必须遵守三点请求契约,写错任意一个都会导致列表为空或接口报「参数校验失败formUuid」:
|
|
315
315
|
|
|
316
316
|
1. **必须 `GET` + query 参数**,`formUuid`/`appType` 放 **URL query**。若用 `POST` 把 `formUuid` 塞进 body,后端从 query 读不到 → 直接报 **`参数校验失败formUuid`**。
|
|
317
317
|
2. **分页参数名是 `currentPage`**(不是 `pageNumber`);`searchFieldJson` 传 `'{}'` 表示不过滤。
|
|
318
318
|
3. **返回列表在 `content.data`**,不是顶层 `data`。响应形如 `{ content: { data: [...], totalCount, currentPage }, success: true }`。上文的 `unwrapRows` 已递归兜底解包,直接用即可。(注意:openyida CLI `data query` 会**归一化**把 `data` 提到顶层,你用 CLI 抽查看到的是顶层 `data`,别被误导——浏览器直连拿到的是 `content.data`。)每行字段值在 `row.formData[fieldId]`,`SelectField`/`RadioField` 已是纯字符串,`DateField` 是 13 位毫秒数。
|
|
319
319
|
|
|
320
320
|
```jsx
|
|
321
|
-
//
|
|
321
|
+
// GET + query,读一个表单的数据
|
|
322
322
|
function fetchFormData(appType, formUuid, signal) {
|
|
323
323
|
var qs = new URLSearchParams({
|
|
324
324
|
formUuid: formUuid,
|
|
@@ -337,20 +337,11 @@ function fetchFormData(appType, formUuid, signal) {
|
|
|
337
337
|
function fieldOf(row, fieldId) { return (row.formData || row)[fieldId]; }
|
|
338
338
|
```
|
|
339
339
|
|
|
340
|
-
##
|
|
341
|
-
|
|
342
|
-
1. **把 Code Canvas 当普通自定义页面写**:Canvas 没有 `this.utils.yida.*` / `dataSourceMap`,必须自写 HTTP 桥。
|
|
343
|
-
2. **CSRF 来源取错**:只从 `document.cookie` 找 token 会失败,因为 Cookie 可能是 HttpOnly;应从 `window.g_config` 取页面上下文 token。
|
|
344
|
-
3. **响应结构只解析一层**:表单查询可能返回 `content.result.data` 这类多层包裹,页面只读 `json.data` 就会显示 0 条。
|
|
345
|
-
4. **Demo 数据掩盖真实错误**:seed 数据让页面看起来“有内容”,但没有证明接口数据真的接入;真实数据页必须用 `totalCount` 做保护,接口异常或未接 dataBinding 时展示错误/空态,不回退成漂亮 demo 列表。
|
|
346
|
-
5. **刷新策略不对**:多人状态同步需要 5 秒左右轮询,但轮询只能刷新数值和列表,不能整页 reload,也不能首屏之后反复清空旧数据。
|
|
347
|
-
6. **排序口径混淆**:数据存在但按点赞排行时,0 赞新数据可能排在后面;验收时要同时看总数和列表排序规则。
|
|
348
|
-
|
|
349
|
-
交付验收清单:
|
|
340
|
+
## 数据接入验收清单
|
|
350
341
|
|
|
351
342
|
- 已确认 appType、formUuid 和字段 ID 来自真实表单 Schema。
|
|
352
343
|
- 页面首屏接口返回后,统计总数与数据管理页 / `openyida data query form` 的总数一致。
|
|
353
|
-
-
|
|
344
|
+
- 真实接口异常时显示错误原因和重试入口。
|
|
354
345
|
- 提交、点赞等写操作成功后调用 silent reload,只更新统计和列表。
|
|
355
346
|
- 轮询 `setInterval` 有 cleanup,页面隐藏时暂停请求。
|
|
356
347
|
|
|
@@ -358,5 +349,5 @@ function fieldOf(row, fieldId) { return (row.formData || row)[fieldId]; }
|
|
|
358
349
|
|
|
359
350
|
- **确认再写**:删除、批量更新等不可逆操作,先让用户在 UI 里显式确认,不在 `useEffect` 里静默触发。
|
|
360
351
|
- **幂等**:提交按钮加 loading 锁与去重键,避免重复写入。
|
|
361
|
-
-
|
|
362
|
-
-
|
|
352
|
+
- **权限**:写操作是否允许由平台权限决定;失败按后端返回的 `errorMsg` 提示。
|
|
353
|
+
- **密钥位置**:任何 `appSecret` / 签名逻辑都留在服务端 / 连接器,Canvas 源码里只出现同源相对路径与业务参数。
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
# Code Canvas 依赖白名单与 CDN 加载
|
|
2
2
|
|
|
3
|
-
本文件承载 Code Canvas 的依赖白名单、windowAlias
|
|
3
|
+
本文件承载 Code Canvas 的依赖白名单、windowAlias 映射与编译改写规则。依赖加载细节以当前宜搭物料运行时为准;本文只保留页面作者需要遵循的 import / CDN 契约。核实自 `vc-deep-yida/src/components/yida-code-canvas` 源码(`dependencies.ts` / `factory.tsx`)。
|
|
4
4
|
|
|
5
5
|
## 依赖白名单(核实自 `yida-code-canvas/dependencies.ts`)
|
|
6
6
|
|
|
7
|
-
编译阶段把 `import` 改写为下列白名单的 `windowAlias` 引用,运行时按 `windowAlias` 加载到 `window` 上。带 `${cdn}`
|
|
7
|
+
编译阶段把 `import` 改写为下列白名单的 `windowAlias` 引用,运行时按 `windowAlias` 加载到 `window` 上。带 `${cdn}` 的资源前缀由平台运行时按当前环境决定。
|
|
8
8
|
|
|
9
9
|
| 包名 | windowAlias | 资源 |
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| react | `React` | g.alicdn.com react 18.3.1 |
|
|
12
12
|
| react-dom | `ReactDOM` | g.alicdn.com react-dom 18.3.1 |
|
|
13
|
-
| antd | `antd` | g.alicdn.com antd **5.23.3** `antd-with-locales.js
|
|
13
|
+
| antd | `antd` | g.alicdn.com antd **5.23.3** `antd-with-locales.js` |
|
|
14
14
|
| @ant-design/icons | `icons` | g.alicdn.com ant-design-icons 5.5.1 |
|
|
15
|
-
| dayjs | `dayjs` | 仅 `assetUrlPlaceholder`(dev CDN 的 locale 文件),**无 `assetUrl`** → 画布自身不会加载 dayjs core,依赖宿主提供 |
|
|
16
15
|
| ahooks | `ahooks` | `${cdn}/platform/yida-assets/ahooks.js`(默认追加) |
|
|
17
16
|
| d3 | `d3` | g.alicdn.com d3 7.9.0 |
|
|
18
17
|
| recharts | `Recharts` | g.alicdn.com recharts 2.15.0 |
|
|
@@ -21,29 +20,10 @@
|
|
|
21
20
|
| framer-motion | `FramerMotion` | `${cdn}/.../framerMotion.js` |
|
|
22
21
|
| yida-plugin-markdown | `YidaMarkdown` | moduleFederation 0.0.4 |
|
|
23
22
|
|
|
24
|
-
新增依赖必须同时满足:① 编译能把 import 抽进 `importedModules` 并映射到 windowAlias(见 `canvas-compile.js` 的 `MODULE_ALIAS_MAP`);② 上表或平台运行时能把依赖加载到 window;③ `runtimeCode` 引用的变量名与 windowAlias 一致;④ CSS
|
|
23
|
+
新增依赖必须同时满足:① 编译能把 import 抽进 `importedModules` 并映射到 windowAlias(见 `canvas-compile.js` 的 `MODULE_ALIAS_MAP`);② 上表或平台运行时能把依赖加载到 window;③ `runtimeCode` 引用的变量名与 windowAlias 一致;④ CSS 资源可加载。页面源码只 import 白名单包;`yida-utils`、`@ali/deep`、原生字段组件等宜搭运行态能力通过 `window.Deep`、`window.DeepYida`、`window.YidaNativeComponents` 等 `window.*` 访问。
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
当宜搭物料依赖表已经先于 OpenYida CLI 升级,且已确认运行时确实会注入某个新裸包时,可以临时设置 `OPENYIDA_CANVAS_ALLOW_UNSUPPORTED_IMPORTS=1` 退回旧式 `window["pkg"]` 映射发布。该开关只用于白名单漂移期间的发布验证;常规页面仍使用上表白名单和明确的 `windowAlias`。
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
真实表单数据绑定使用页面内本地 `useYidaData(binding)`、`DataBridge` 与同源 `fetch` 实现。
|
|
29
28
|
|
|
30
29
|
编译位置:OpenYida CLI **本地用 Babel** 把源码转译为 `runtimeCode` + `importedModules`(`import`→`window.<别名>`、`export default`→`YidaComp`、依赖名正则抽取),不调用任何在线编译服务,因此不依赖登录态、不经过风控。别名映射逐条镜像自 `dependencies.ts` 的 `getModuleAliasMap()`;运行时消费契约见 `factory.tsx`(`new Function` 执行 `runtimeCode` 取 `YidaComp`)。
|
|
31
|
-
|
|
32
|
-
## 预发正常、线上报 `antd is not defined` 的根因
|
|
33
|
-
|
|
34
|
-
现象:预发(`pre-*.alibaba-inc.com`)页面正常;线上(如 `*.aliwork.com`)白屏,控制台报 `antd is not defined` + `antd-with-locales.js` / `dayjs.js` 抛 `Cannot read properties of undefined (reading 'extend')`。
|
|
35
|
-
|
|
36
|
-
根因(核实自源码):
|
|
37
|
-
|
|
38
|
-
- `antd-with-locales.js`(UMD)初始化时会执行 `dayjs.extend(...)`,其中 `dayjs` 是**外部依赖**,解析为 `window.dayjs`。若加载 antd 前 `window.dayjs` 未就绪 → `undefined.extend` 抛错 → antd 模块未定义 → 业务代码引用 `antd` 报 `antd is not defined`。
|
|
39
|
-
- 正确顺序见 `vc-procode-comp/view.js`:先 `window.dayjs = window.__YCCommon?.Common?.dayjs` 再注入 antd。**但 `yida-code-canvas/factory.tsx` 原实现没有这步**:它 `loadDependencies` 时对 antd 只 `push(assetUrl)`,而 dayjs 条目只有 `assetUrlPlaceholder`、无 `assetUrl`,画布自身根本不会加载 dayjs;且加载前 `if (window[windowAlias]) return` 会跳过已存在依赖。
|
|
40
|
-
- 于是环境差异被放大:
|
|
41
|
-
- **预发**:宿主设计器 / 同页其它 procode 组件已把 `window.antd`(含 dayjs)挂到全局 → 画布命中 `if (window.antd) return`,直接复用宿主 antd,正常。
|
|
42
|
-
- **线上该租户域**:宿主未预置 `window.antd` / `window.dayjs` → 画布现加载 `antd-with-locales.js`,但没有先设 `window.dayjs` → antd 初始化即抛错。(浏览器 debugger 里可见 `finalDependencies` 含 `antd` 却不含 `dayjs`,`window.dayjs` 为 `undefined`,即命中此缺陷。)
|
|
43
|
-
- 附带因素:`isProd = location.hostname.indexOf('pre-') === -1` 是脆弱的域名启发式,非 `pre-` 前缀域一律判为线上,走 `g.alicdn.com` 前缀;antd 本身两端都硬编码 `g.alicdn.com`,故该差异不是 antd 主因,但会影响 `${cdn}` 类依赖(ahooks/radix/lucide/framer-motion/tailwind)的可达性。
|
|
44
|
-
|
|
45
|
-
## 物料侧修复方向
|
|
46
|
-
|
|
47
|
-
这是**物料层缺陷**(`factory.tsx` 未在 antd 前保证 `window.dayjs`),页面作者难以在 Canvas 源码内自救(`import dayjs` 也因 dayjs 无 `assetUrl` 不落地)。正确修复在 `factory.tsx` 的 `loadDependencies`:当 `finalDependencies` 含 `antd` 且 `window.dayjs` 未就绪时,**先**复用宿主 `window.__YCCommon?.Common?.dayjs`,否则**单独 `await` 加载 dayjs core**(如 `g.alicdn.com/code/lib/dayjs/<ver>/dayjs.min.js`),确保早于 antd 脚本执行,再进入原有 `assetsUrls` 批量加载。要点:dayjs 必须在**独立且被 await 的加载步骤**里先就绪,避免与 antd 放同一批并行加载产生竞态。
|
|
48
|
-
|
|
49
|
-
临时规避(未改物料时):让宿主页先行加载 antd/dayjs,或页面改用不依赖 dayjs 的轻组件(避开 DatePicker、时间 locale 等触发 `dayjs.extend` 的能力)。
|
|
@@ -1,42 +1,74 @@
|
|
|
1
1
|
# Code Canvas 运行时事实与 EmployeeField 验证
|
|
2
2
|
|
|
3
|
-
本文件承载 `yida-canvas-custom-page`
|
|
3
|
+
本文件承载 `yida-canvas-custom-page` 的运行时边界与 EmployeeField 验证示例,SKILL.md 只保留摘要与链接。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 运行时事实
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- `
|
|
9
|
-
- 代码经 `new Function` 包裹执行,wrapper 只注入 `window`(`iframeWindow` / `parentWindow`),**不注入 `this` 上下文**。因此 `YidaComp` 是普通 React 函数组件,**`this.utils.yida.*`、`this.dataSourceMap`、`export function didMount()` 等普通页面契约都不可用**。
|
|
7
|
+
- Code Canvas 源码在宿主页 `window` 中执行,`YidaComp` 是普通 React 函数组件。
|
|
8
|
+
- Canvas 使用 React 函数组件上下文;数据读写、生命周期和渲染通过 hooks、props、HTTP 数据桥或连接器完成。需要 `this.utils.yida.*`、`this.dataSourceMap`、`this.$(fieldId)`、`export function didMount()` 等普通页面契约时,使用 `yida-custom-page`。
|
|
10
9
|
- 代码执行后必须返回 `YidaComp`、`YidaComp.default` 或组件函数。
|
|
11
|
-
- Canvas
|
|
10
|
+
- Canvas 要读写宜搭数据,只能在组件内使用 HTTP 数据桥、连接器代理或显式 props 注入。如果用户明确要求普通自定义页面 JSX/Jsx 组件链路,或页面强依赖普通自定义页实例桥,选择 `yida-custom-page`。
|
|
12
11
|
|
|
13
|
-
>
|
|
12
|
+
> 依赖白名单表、windowAlias 映射与编译端点已拆到 [dependencies-and-cdn.md](dependencies-and-cdn.md)。
|
|
14
13
|
|
|
15
14
|
## 宜搭原生组件判断
|
|
16
15
|
|
|
17
|
-
`EmployeeField`、`SelectField`、`DepartmentSelectField`、`AttachmentField`
|
|
16
|
+
`EmployeeField`、`SelectField`、`DepartmentSelectField`、`AttachmentField` 等宜搭原生字段组件按运行态组件接入。使用前确认:
|
|
18
17
|
|
|
19
|
-
- `
|
|
20
|
-
-
|
|
21
|
-
- 组件所需页面上下文、组织权限、弹层容器、移动端版本均可用。
|
|
18
|
+
- 宿主 `window.Deep` / `window.DeepYida` / `window.YidaNativeComponents` 能探测到目标组件。
|
|
19
|
+
- 组件所需 CSS、页面上下文、组织权限、弹层容器、移动端版本均可用。
|
|
22
20
|
- `onChange` 返回值结构能被后续数据保存或查询逻辑消费。
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
这些原生组件从宿主 `window` 探测,不从 `@ali/deep` 等裸包 import。确认条件齐全时渲染原生组件;确认条件不足时使用普通 UI:用 antd 或自定义控件选择候选用户,值只存已知 userId / unionId / 文本快照。
|
|
25
23
|
|
|
26
24
|
## EmployeeField 验证示例
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
示例用于 Code Canvas 验证;普通 `.oyd.jsx` 自定义页使用 `yida-custom-page` 的实例桥写法。
|
|
29
27
|
|
|
30
28
|
```jsx
|
|
31
|
-
import React
|
|
32
|
-
|
|
29
|
+
import React from 'react';
|
|
30
|
+
|
|
31
|
+
function findEmployeeField() {
|
|
32
|
+
var sources = [];
|
|
33
|
+
if (window.Deep) { sources.push(window.Deep); }
|
|
34
|
+
if (window.YidaNativeComponents) { sources.push(window.YidaNativeComponents); }
|
|
35
|
+
if (window.DeepYida) {
|
|
36
|
+
sources.push(window.DeepYida.default || window.DeepYida);
|
|
37
|
+
if (Array.isArray(window.DeepYida)) {
|
|
38
|
+
sources = sources.concat(window.DeepYida);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (var i = 0; i < sources.length; i += 1) {
|
|
43
|
+
var source = sources[i];
|
|
44
|
+
if (source && source.EmployeeField) {
|
|
45
|
+
return source.EmployeeField;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
33
50
|
|
|
34
51
|
function YidaComp(props) {
|
|
35
|
-
var
|
|
36
|
-
var state =
|
|
52
|
+
var EmployeeField = findEmployeeField();
|
|
53
|
+
var state = React.useState([]);
|
|
37
54
|
var value = state[0];
|
|
38
55
|
var setValue = state[1];
|
|
39
56
|
|
|
57
|
+
if (!EmployeeField) {
|
|
58
|
+
return (
|
|
59
|
+
<div style={{ padding: 16 }}>
|
|
60
|
+
<label style={{ display: 'block', marginBottom: 8 }}>负责人</label>
|
|
61
|
+
<input
|
|
62
|
+
placeholder="EmployeeField 不可用,使用文本 fallback"
|
|
63
|
+
onChange={function (event) {
|
|
64
|
+
setValue([{ name: event.target.value, raw: { fallback: true } }]);
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
<pre style={{ marginTop: 12, fontSize: 12 }}>{JSON.stringify(value, null, 2)}</pre>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
40
72
|
return (
|
|
41
73
|
<div style={{ padding: 16 }}>
|
|
42
74
|
<EmployeeField
|
|
@@ -44,14 +76,11 @@ function YidaComp(props) {
|
|
|
44
76
|
placeholder="请选择负责人"
|
|
45
77
|
multiple={false}
|
|
46
78
|
value={value}
|
|
47
|
-
onChange={(nextValue)
|
|
48
|
-
console.log('employee value', nextValue);
|
|
79
|
+
onChange={function (nextValue) {
|
|
49
80
|
setValue(nextValue || []);
|
|
50
81
|
}}
|
|
51
82
|
/>
|
|
52
|
-
<pre style={{ marginTop: 12, fontSize: 12 }}>
|
|
53
|
-
{JSON.stringify(value, null, 2)}
|
|
54
|
-
</pre>
|
|
83
|
+
<pre style={{ marginTop: 12, fontSize: 12 }}>{JSON.stringify(value, null, 2)}</pre>
|
|
55
84
|
</div>
|
|
56
85
|
);
|
|
57
86
|
}
|
|
@@ -61,7 +90,7 @@ export default YidaComp;
|
|
|
61
90
|
|
|
62
91
|
验收点:
|
|
63
92
|
|
|
64
|
-
-
|
|
93
|
+
- 组件探测结果能明确显示可用或缺失,不因缺失组件白屏。
|
|
65
94
|
- 页面控制台没有 `EmployeeField is not defined`、样式缺失、弹层挂载错误。
|
|
66
95
|
- 成员弹层能打开、搜索、选择、清空。
|
|
67
96
|
- PC 和移动端都能完成选择。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 核心策略
|
|
6
6
|
|
|
7
|
-
Code Canvas
|
|
7
|
+
Code Canvas 里的宜搭运行态组件按“先探测、可用再增强、不可用就 fallback”的方式接入。字段、门户、数据管理视图等运行态组件统一从宿主 `window.Deep` / `window.DeepYida` / `window.YidaNativeComponents` 查找;页面源码只 `import` Code Canvas 白名单内的通用前端包。
|
|
8
8
|
|
|
9
9
|
推荐方式是运行时桥接:
|
|
10
10
|
|
|
@@ -28,7 +28,7 @@ openyida sample yida-canvas-custom-page portal-native-components --output projec
|
|
|
28
28
|
| --- | --- |
|
|
29
29
|
| `window.Deep[name]` | `@ali/deep` 基础字段/组件全局 |
|
|
30
30
|
| `window.DeepYida.default` 或 bundle 数组 | `vc-deep-yida` 运行包组件集合,按 `displayName` 匹配 |
|
|
31
|
-
| `window.YidaNativeComponents[name]` |
|
|
31
|
+
| `window.YidaNativeComponents[name]` | 可选兼容入口;存在时读取,不作为前置条件 |
|
|
32
32
|
|
|
33
33
|
业务代码统一走桥接函数读取宿主组件,便于隔离不同运行态差异。
|
|
34
34
|
|
|
@@ -47,17 +47,17 @@ openyida sample yida-canvas-custom-page portal-native-components --output projec
|
|
|
47
47
|
|
|
48
48
|
- Banner 只传 `mainTitle`、`subTitle`、`bannerHeight`、`textPosition` 等稳定展示 props。
|
|
49
49
|
- QuickEntry 只传静态 `content`、`titleConfig`、`themeConfig`。
|
|
50
|
-
- 点击跳转由 Canvas
|
|
50
|
+
- 点击跳转由 Canvas 自己控制,目标 URL 和打开方式写在页面代码里。
|
|
51
51
|
|
|
52
52
|
### QuickAccessCard / RecentlyUsedCard(可用,但 `theme` 必传)
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
这两个是**容器型组件**,会在运行态自行拉取应用列表并渲染卡片。`theme` 是必传运行时契约;页面始终传入 `theme="row-white"` 或 `theme="column"`。
|
|
55
55
|
|
|
56
56
|
必传 / 建议 props:
|
|
57
57
|
|
|
58
58
|
| prop | 必要性 | 说明 |
|
|
59
59
|
| --- | --- | --- |
|
|
60
|
-
| `theme` | **必传** | 字符串。含 `column` →
|
|
60
|
+
| `theme` | **必传** | 字符串。含 `column` → 纵向排布,否则横向。推荐 `'row-white'`(横排)或 `'column'` |
|
|
61
61
|
| `maxItems` | 建议 | 展示数量上限,缺省 8 |
|
|
62
62
|
| `showAppDescription` | 可选 | 是否显示应用描述 |
|
|
63
63
|
| `containerPrefix` | 可选 | 容器 className 前缀 |
|
|
@@ -66,21 +66,21 @@ openyida sample yida-canvas-custom-page portal-native-components --output projec
|
|
|
66
66
|
|
|
67
67
|
使用要求:
|
|
68
68
|
|
|
69
|
-
-
|
|
70
|
-
- 列表数据由组件自取(依赖当前登录用户 + 门户接口),Canvas
|
|
71
|
-
-
|
|
69
|
+
- **始终传 `theme`**(如 `'row-white'`)。
|
|
70
|
+
- 列表数据由组件自取(依赖当前登录用户 + 门户接口),Canvas 只负责容器 props、布局和 fallback。
|
|
71
|
+
- 组件缺失或无门户接口权限时,渲染 Canvas 自绘应用入口卡片。
|
|
72
72
|
|
|
73
|
-
>
|
|
73
|
+
> 页面侧遵守必传 props 约束并做好局部降级:`theme` 有值,组件缺失或运行态不兼容时展示 Canvas fallback。
|
|
74
74
|
|
|
75
|
-
### DataCard
|
|
75
|
+
### DataCard 使用边界
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
数据卡片采用 Canvas 自绘卡片 + `fetch`/连接器/`yida-report` 取数。`DataCard` 需要完整门户数据卡片上下文,只有目标运行态确认该上下文可用时才接入。
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
页面只需要「门户风格」时,使用 Canvas 自绘卡片并通过 fetch/连接器取数据;需要复用宜搭门户内置的快捷/最近应用卡片时,按上面方式启用 `QuickAccessCard` / `RecentlyUsedCard`。
|
|
80
80
|
|
|
81
81
|
## 数据管理视图怎么用
|
|
82
82
|
|
|
83
|
-
需要在自定义页面中嵌入门户里那块「数据管理视图」时,优先探测 `DataManageViews
|
|
83
|
+
需要在自定义页面中嵌入门户里那块「数据管理视图」时,优先探测 `DataManageViews`,并把它当作黑盒组件使用。页面侧只传稳定的 `form` 配置,不自行构造底层数据管理 props。
|
|
84
84
|
|
|
85
85
|
适用场景:
|
|
86
86
|
|
|
@@ -127,14 +127,14 @@ openyida sample yida-canvas-custom-page native-components-smoke --output project
|
|
|
127
127
|
|
|
128
128
|
使用要求:
|
|
129
129
|
|
|
130
|
-
-
|
|
131
|
-
- 组件依赖宿主运行态、登录态、权限、CSRF、`vc-deep-yida` 与 `yc-data-manage`
|
|
132
|
-
- `DataManageViews` 会自动过滤 `viewType === 'form'`
|
|
133
|
-
-
|
|
130
|
+
- 先拿到 `form.value/formUuid`,再渲染 `DataManageViews`。
|
|
131
|
+
- 组件依赖宿主运行态、登录态、权限、CSRF、`vc-deep-yida` 与 `yc-data-manage` 样式;组件缺失或权限不足时保留 Canvas fallback。
|
|
132
|
+
- `DataManageViews` 会自动过滤 `viewType === 'form'` 的视图,并关闭导入、导出、批量操作等门户不需要的能力;页面侧统一使用它承载门户数据管理视图。
|
|
133
|
+
- 只需要展示少量业务数据时,用 Canvas 自绘表格 + HTTP 数据桥 / 连接器 / `openyida data`;需要复用门户数据管理视图时使用 `DataManageViews`。
|
|
134
134
|
|
|
135
135
|
## 成员组件怎么用
|
|
136
136
|
|
|
137
|
-
需要成员选择时,优先探测 `EmployeeField
|
|
137
|
+
需要成员选择时,优先探测 `EmployeeField`。它属于宿主运行态组件,先验证可用性,再接入业务页面。
|
|
138
138
|
|
|
139
139
|
使用要求:
|
|
140
140
|
|
|
@@ -158,7 +158,7 @@ openyida sample yida-canvas-custom-page native-components-smoke --output project
|
|
|
158
158
|
|
|
159
159
|
## 部门组件怎么用
|
|
160
160
|
|
|
161
|
-
需要部门选择时,优先探测 `DepartmentSelectField
|
|
161
|
+
需要部门选择时,优先探测 `DepartmentSelectField`。该组件依赖宿主通讯录能力、搜索接口和权限上下文,因此要比成员组件更谨慎。
|
|
162
162
|
|
|
163
163
|
使用要求:
|
|
164
164
|
|
|
@@ -190,9 +190,9 @@ openyida sample yida-canvas-custom-page native-components-smoke --output project
|
|
|
190
190
|
|
|
191
191
|
使用要求:
|
|
192
192
|
|
|
193
|
-
-
|
|
193
|
+
- 原生上传作为增强能力;组件不可用或上传失败时,fallback 到链接录入或业务连接器上传。
|
|
194
194
|
- Cookie、CSRF、OSS key 或内部上传密钥由平台、连接器或后端服务管理,Canvas 只消费安全返回结果。
|
|
195
|
-
- 提交数据只使用归一化后的文件数组,`raw`
|
|
195
|
+
- 提交数据只使用归一化后的文件数组,`raw` 仅用于检查。
|
|
196
196
|
|
|
197
197
|
推荐归一化结构:
|
|
198
198
|
|
|
@@ -234,4 +234,4 @@ openyida sample yida-canvas-custom-page native-components-smoke --output project
|
|
|
234
234
|
- 上传组件尚未完成 OSS 签名或上传权限校验。
|
|
235
235
|
- 移动端组件形态与 PC 不一致且未适配。
|
|
236
236
|
|
|
237
|
-
|
|
237
|
+
Canvas 自绘 fallback 是页面稳定基线;原生组件是增强体验。
|
|
@@ -4,24 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
## 首次生成模板路由
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
用户描述页面目标后,按下表把自然语言需求路由到确定模板。
|
|
8
8
|
|
|
9
|
-
`generate-page`
|
|
9
|
+
`generate-page` 的模板提供运行时契约、数据桥、主题变量和首版 primitives。生成真实页面时,结合 `yida-page-uiux` 的视觉方向决策块,产出业务化区块顺序、信息层级、局部构图、文案和样式节奏。保留模板的编译安全结构和必要 primitive class,替换为当前业务的 Hero、卡片、卖点和文案。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
页面生成路径二选一:走模板路径时,先写业务化 `page-spec.json` 并执行 `openyida generate-page ... --spec ... --compile`,之后读取 CLI 摘要或 `.openyida-page.json`,再对生成源码做小范围 Edit/patch;已经明确最终页面结构、数据桥和视觉细节时,走手写路径,直接 Write 最终 `.canvas.jsx`。
|
|
12
12
|
|
|
13
13
|
生成器会在 `.openyida-page.json` 中写入 `domainFidelity`,并在 CLI 输出中提示当前页面是否还依赖 sample fallback:
|
|
14
14
|
|
|
15
15
|
- `domain-ready`:主要业务语义已覆盖,sample 只剩编译骨架。
|
|
16
16
|
- `draft-needs-domain-spec`:用户已有业务要求,但 page spec 仍缺业务对象、指标、交互或视觉方向;继续补 spec 或改源码。
|
|
17
|
-
- `sample-reference
|
|
17
|
+
- `sample-reference`:业务化输入不足,结果定位为 sample 参考;继续补业务对象、字段、指标、视觉方向和数据绑定后再作为真实应用页面交付。
|
|
18
18
|
|
|
19
|
-
真实业务页的 `page-spec.json`
|
|
19
|
+
真实业务页的 `page-spec.json` 至少写清业务名称与定位、业务模块/对象、指标口径、用户动作或下钻方式、视觉方向;看板/列表/详情如果本轮已经创建或解析业务表单,写入 `dataBinding.mode=form`、真实 `appType/formUuid` 和字段映射;官网/品牌页优先写 `assets` 或素材缺口。`domainFidelity.sampleFallbacks` 里出现 `features`、`metrics`、`roadmap`、`heroText` 等关键项时,继续补齐业务化规格。
|
|
20
20
|
|
|
21
21
|
数据真实性边界:
|
|
22
22
|
|
|
23
23
|
- `openyida sample` 或模板原样发布可以展示 sample/seed 数据,但页面必须标注 sample/seed。
|
|
24
|
-
-
|
|
24
|
+
- 完整应用或真实交付页使用真实业务记录;需要演示数据时,先把 demo/mock records 写入真实宜搭表单,再由 Canvas 读取。
|
|
25
25
|
- 未写入 demo records 且没有真实数据时,页面应展示空态、表单入口、刷新/登记按钮和 dataBinding 接入提示。
|
|
26
26
|
|
|
27
27
|
| 用户需求 | CLI 模板 | scene | 视觉要点 |
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
| 主从分栏、工单处理台、左列表右详情 | `split-pane-detail` | `list` | 左侧队列、右侧详情、时间线、动作区 |
|
|
36
36
|
| 页面内门户壳、多入口门户、隐藏导航门户 | `portal-shell-home` | `workbench` | 自绘门户导航、角色入口、常用应用、动态摘要 |
|
|
37
37
|
|
|
38
|
-
如果用户要求“门户组件 / 成员 / 部门 / 上传组件”,继续使用 Code Canvas,但按 [native-components-bridge.md](native-components-bridge.md) 选择 `portal-native-components`
|
|
38
|
+
如果用户要求“门户组件 / 成员 / 部门 / 上传组件”,继续使用 Code Canvas,但按 [native-components-bridge.md](native-components-bridge.md) 选择 `portal-native-components` 示例或桥接规则。
|
|
39
39
|
|
|
40
40
|
当模板本身包含页面内应用导航(如 `workbench-home` 的侧边导航、`portal-shell-home` 的门户导航)时,生成的 `.openyida-page.json` 会默认写入 `appBlueprint.renderNav: false` / `navConfig.isRenderNav: false`。发布后必须用 `openyida update-form-config <appType> <formUuid> false "<页面标题>"` 隐藏宜搭原应用导航,避免双导航。
|
|
41
41
|
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
命中 `official-homepage` 时,写代码前先形成轻量设计规格和素材清单。
|
|
45
45
|
|
|
46
|
-
强视觉品牌先读 `yida-page-uiux/references/landing/realistic-brand-homepage.md
|
|
46
|
+
强视觉品牌先读 `yida-page-uiux/references/landing/realistic-brand-homepage.md`。官网完成条件包括:场景 Hero、产品/服务、过程/空间三类素材,从真实材质推导的页面级品牌 token,不同 section 的构图节奏,以及一个明确 CTA。
|
|
47
47
|
|
|
48
48
|
素材清单至少包含:
|
|
49
49
|
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
2. AI 生成图片。先生成本地图片,再确认 CDN 配置,之后上传并回填 URL。
|
|
66
66
|
3. 公开图库。只使用可公开访问且通过 HTTP 200 校验的图片 URL;生产交付优先转存到自有 CDN。
|
|
67
67
|
|
|
68
|
-
若 `openyida cdn-config --show` 显示缺少 `accessKeyId/accessKeySecret/cdnDomain/ossBucket
|
|
68
|
+
若 `openyida cdn-config --show` 显示缺少 `accessKeyId/accessKeySecret/cdnDomain/ossBucket`,交付状态标为“素材待上传”;可先用已验证公开 URL 测试,或提示用户补 CDN 配置。
|
|
69
69
|
|
|
70
|
-
官方 Sample / 离线展示在无 CDN 时允许内嵌经过压缩的 JPEG/WebP data URI,保证源码原样发布也有真实图片;建议 3-5 张、单张不超过 250 KB、总量不超过 800 KB
|
|
70
|
+
官方 Sample / 离线展示在无 CDN 时允许内嵌经过压缩的 JPEG/WebP data URI,保证源码原样发布也有真实图片;建议 3-5 张、单张不超过 250 KB、总量不超过 800 KB。生产页面使用稳定 CDN 素材 URL。
|
|
71
71
|
|
|
72
72
|
## 主题作用域
|
|
73
73
|
|