openyida 2026.7.18 → 2026.7.21

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.
Files changed (200) hide show
  1. package/README.md +37 -2
  2. package/bin/yida.js +113 -18
  3. package/docs/capabilities.md +202 -0
  4. package/lib/agent-center/agent-center.js +2 -3
  5. package/lib/app/app-list.js +3 -4
  6. package/lib/app/build-page.js +13 -6
  7. package/lib/app/check-page.js +16 -6
  8. package/lib/app/compile.js +17 -7
  9. package/lib/app/create-app.js +14 -2
  10. package/lib/app/create-form/api-path.js +25 -0
  11. package/lib/app/create-form/args.js +13 -0
  12. package/lib/app/create-form/commands.js +4 -0
  13. package/lib/app/create-form/definition-reader.js +23 -23
  14. package/lib/app/create-form/field-normalizers.js +26 -7
  15. package/lib/app/create-form/schema-patch.js +4 -1
  16. package/lib/app/create-form.js +155 -68
  17. package/lib/app/create-page.js +47 -10
  18. package/lib/app/generate-page.js +20 -1
  19. package/lib/app/get-form-config.js +2 -1
  20. package/lib/app/get-schema.js +67 -15
  21. package/lib/app/import-app.js +94 -42
  22. package/lib/app/list-forms.js +4 -8
  23. package/lib/app/page-ir.js +140 -0
  24. package/lib/app/publish.js +289 -556
  25. package/lib/app/schema-field-resolution.js +370 -0
  26. package/lib/app/services/app-reader.js +85 -0
  27. package/lib/app/services/app-service.js +235 -0
  28. package/lib/app/services/canvas-page-compiler.js +91 -0
  29. package/lib/app/services/canvas-page-schema-builder.js +149 -0
  30. package/lib/app/services/field-bindings.js +68 -0
  31. package/lib/app/services/form-compiler.js +1922 -0
  32. package/lib/app/services/form-mode-service.js +182 -0
  33. package/lib/app/services/form-schema-patcher.js +333 -0
  34. package/lib/app/services/form-schema-reader.js +59 -0
  35. package/lib/app/services/form-service.js +379 -0
  36. package/lib/app/services/form-validation.js +562 -0
  37. package/lib/app/services/native-page-compiler.js +92 -0
  38. package/lib/app/services/native-page-schema-builder.js +428 -0
  39. package/lib/app/services/page-resource-service.js +185 -0
  40. package/lib/app/update-app.js +22 -9
  41. package/lib/app/update-form-config.js +4 -2
  42. package/lib/asset/asset-cmd.js +19 -6
  43. package/lib/auth/oauth-loopback.js +376 -15
  44. package/lib/auth/token-auth.js +34 -3
  45. package/lib/auth/token-store.js +22 -4
  46. package/lib/basic-info/basic-info.js +2 -1
  47. package/lib/bridge/bridge.js +43 -18
  48. package/lib/core/agent-capabilities.js +5 -3
  49. package/lib/core/command-errors.js +38 -0
  50. package/lib/core/command-manifest.js +59 -1
  51. package/lib/core/copy.js +12 -0
  52. package/lib/core/doctor.js +15 -4
  53. package/lib/core/env-cmd.js +1 -1
  54. package/lib/core/env.js +7 -6
  55. package/lib/core/i18n.js +66 -8
  56. package/lib/core/legacy-schema-guard.js +408 -0
  57. package/lib/core/locales/en.js +38 -46
  58. package/lib/core/locales/zh.js +30 -46
  59. package/lib/core/sample.js +12 -2
  60. package/lib/core/utils.js +334 -66
  61. package/lib/core/yida-client.js +108 -5
  62. package/lib/corp-efficiency/corp-efficiency.js +2 -2
  63. package/lib/corp-manager/corp-manager.js +3 -3
  64. package/lib/formula/evaluate.js +11 -68
  65. package/lib/formula/field-refs.js +83 -0
  66. package/lib/i18n-management/i18n-management.js +2 -3
  67. package/lib/process/configure-process.js +44 -1992
  68. package/lib/process/create-process.js +54 -87
  69. package/lib/process/preview-process.js +20 -8
  70. package/lib/process/services/process-compiler.js +2056 -0
  71. package/lib/process/services/process-reader.js +232 -0
  72. package/lib/process/services/process-resource-service.js +571 -0
  73. package/lib/process/services/process-service.js +122 -0
  74. package/lib/process/services/process-stage-checkpoint.js +246 -0
  75. package/lib/report/append.js +7 -26
  76. package/lib/report/http.js +31 -5
  77. package/lib/report/index.js +10 -2
  78. package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
  79. package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
  80. package/lib/samples/yida-canvas-custom-page/dashboard-starter.canvas.jsx +5 -2
  81. package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
  82. package/lib/samples/yida-canvas-custom-page/portal-shell-home.canvas.jsx +2 -2
  83. package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +206 -10
  84. package/lib/samples/yida-custom-page/data-management.oyd.jsx +14 -3
  85. package/lib/samples/yida-custom-page/design-tokens.js +2 -2
  86. package/lib/samples/yida-custom-page/detail-profile.oyd.jsx +1 -1
  87. package/lib/samples/yida-custom-page/portal-shell-home.oyd.jsx +7 -2
  88. package/lib/samples/yida-custom-page/split-pane-detail.oyd.jsx +2 -1
  89. package/lib/schema/adapters/app-adapter.js +210 -0
  90. package/lib/schema/adapters/form-adapter.js +1362 -0
  91. package/lib/schema/adapters/keys.js +19 -0
  92. package/lib/schema/adapters/page-adapter.js +566 -0
  93. package/lib/schema/adapters/process-adapter.js +519 -0
  94. package/lib/schema/applier.js +1878 -0
  95. package/lib/schema/apply-store.js +1083 -0
  96. package/lib/schema/command.js +645 -0
  97. package/lib/schema/dependency-graph.js +83 -0
  98. package/lib/schema/errors.js +481 -0
  99. package/lib/schema/hash.js +9 -0
  100. package/lib/schema/manifest-limits.js +177 -0
  101. package/lib/schema/manifest-loader.js +309 -0
  102. package/lib/schema/manifest-schema-v1.json +193 -0
  103. package/lib/schema/normalize-manifest.js +281 -0
  104. package/lib/schema/page-canvas-foundation.js +447 -0
  105. package/lib/schema/page-data-source-builder.js +561 -0
  106. package/lib/schema/page-foundation.js +556 -0
  107. package/lib/schema/page-source-loader.js +314 -0
  108. package/lib/schema/planner.js +691 -0
  109. package/lib/schema/remote-dispatch-boundary.js +39 -0
  110. package/lib/schema/remote-missing.js +21 -0
  111. package/lib/schema/remote-reader.js +189 -0
  112. package/lib/schema/resource-registry.js +157 -0
  113. package/lib/schema/server-revision.js +71 -0
  114. package/lib/schema/sort.js +28 -0
  115. package/lib/schema/state-store.js +589 -0
  116. package/package.json +10 -8
  117. package/scripts/check-release-risks.js +254 -0
  118. package/scripts/generate-command-docs.js +6 -1
  119. package/scripts/i18n-baseline.json +11 -11
  120. package/scripts/postinstall.js +8 -12
  121. package/scripts/validate-ci.sh +15 -11
  122. package/scripts/validate-i18n.js +30 -9
  123. package/scripts/validate-package-size.js +5 -2
  124. package/scripts/validate-skills.js +4 -0
  125. package/scripts/validate-structure.js +15 -0
  126. package/yida-skills/SKILL.md +117 -30
  127. package/yida-skills/references/schema-as-code-phase1.md +99 -0
  128. package/yida-skills/references/setup-and-env.md +59 -59
  129. package/yida-skills/references/task-retrospective.md +6 -6
  130. package/yida-skills/skills/yida-app/SKILL.md +78 -17
  131. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
  132. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
  133. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +15 -0
  134. package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
  135. package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
  136. package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
  137. package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
  138. package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
  139. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  140. package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
  141. package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
  142. package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
  143. package/yida-skills/skills/yida-integration/SKILL.md +7 -1
  144. package/yida-skills/skills/yida-login/SKILL.md +50 -99
  145. package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
  146. package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
  147. package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
  148. package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
  149. package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
  150. package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
  151. package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
  152. package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
  153. package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
  154. package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
  155. package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
  156. package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
  157. package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
  158. package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
  159. package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
  160. package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
  161. package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
  162. package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
  163. package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
  164. package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
  165. package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
  166. package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
  167. package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
  168. package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
  169. package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
  170. package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
  171. package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
  172. package/yida-skills/skills/yida-report/SKILL.md +9 -235
  173. package/yida-skills/skills/yida-report/references/schema-builder-details.md +239 -0
  174. package/yida-skills/skills/yida-skill-evaluator/SKILL.md +170 -0
  175. package/yida-skills/skills-index.json +238 -54
  176. package/lib/core/locales/ar.js +0 -834
  177. package/lib/core/locales/de.js +0 -834
  178. package/lib/core/locales/es.js +0 -834
  179. package/lib/core/locales/fr.js +0 -834
  180. package/lib/core/locales/hi.js +0 -834
  181. package/lib/core/locales/ja.js +0 -1227
  182. package/lib/core/locales/ko.js +0 -836
  183. package/lib/core/locales/pt.js +0 -834
  184. package/lib/core/locales/vi.js +0 -834
  185. package/lib/core/locales/zh-HK.js +0 -1263
  186. package/project/pages/src/demo-birthday-game.oyd.jsx +0 -832
  187. package/project/pages/src/demo-chip-insight.oyd.jsx +0 -983
  188. package/project/pages/src/demo-compat-smoke.oyd.jsx +0 -58
  189. package/project/pages/src/demo-crm-batch-entry.oyd.jsx +0 -805
  190. package/project/pages/src/demo-crm-dashboard.oyd.jsx +0 -677
  191. package/project/pages/src/demo-future-vision-2026.oyd.jsx +0 -1102
  192. package/project/pages/src/demo-ppt.oyd.jsx +0 -1192
  193. package/project/pages/src/demo-salary-calculator.oyd.jsx +0 -904
  194. package/project/pages/src/openyida-knowledge-doc.oyd.jsx +0 -1714
  195. package/yida-skills/skills/large-file-write/SKILL.md +0 -93
  196. package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
  197. package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
  198. package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
  199. package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
  200. package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
@@ -6,7 +6,8 @@ const { lintYidaSource, printLintResult } = require('./page-linter');
6
6
  const { buildPageSource, shouldBuildPageSource } = require('./page-compat');
7
7
  const { warnLargePageSource } = require('./page-size-guard');
8
8
  const { t } = require('../core/i18n');
9
- const { warn, error, hint } = require('../core/chalk');
9
+ const { warn, hint } = require('../core/chalk');
10
+ const { throwCommandError, throwUsage } = require('../core/command-errors');
10
11
 
11
12
  function parseArgs(args) {
12
13
  return {
@@ -20,14 +21,17 @@ async function run(args) {
20
21
  const options = parseArgs(args || []);
21
22
 
22
23
  if (!options.sourceFile) {
23
- warn(t('cli.check_page_usage'));
24
- warn(t('cli.check_page_example'));
25
- process.exit(1);
24
+ throwUsage(t('cli.check_page_usage'), t('cli.check_page_example'), {
25
+ code: 'CHECK_PAGE_INVALID_ARGUMENTS',
26
+ });
26
27
  }
27
28
 
28
29
  const sourcePath = path.resolve(options.sourceFile);
29
30
  if (!fs.existsSync(sourcePath)) {
30
- error(t('publish.source_not_found', sourcePath));
31
+ throwCommandError(t('publish.source_not_found', sourcePath), {
32
+ code: 'CHECK_PAGE_SOURCE_NOT_FOUND',
33
+ details: { sourcePath },
34
+ });
31
35
  }
32
36
 
33
37
  const sourceCode = fs.readFileSync(sourcePath, 'utf-8');
@@ -63,7 +67,13 @@ async function run(args) {
63
67
  }
64
68
 
65
69
  if (!ok) {
66
- process.exit(1);
70
+ throwCommandError(t('check_page.failed'), {
71
+ code: 'CHECK_PAGE_FAILED',
72
+ details: {
73
+ errors: lintResult.errors,
74
+ buildErrors,
75
+ },
76
+ });
67
77
  }
68
78
  }
69
79
 
@@ -7,7 +7,8 @@ const { runLintCheck } = require('./page-linter');
7
7
  const { buildPageFile, shouldBuildPageSource } = require('./page-compat');
8
8
  const { warnLargePageSource } = require('./page-size-guard');
9
9
  const { t } = require('../core/i18n');
10
- const { warn, error, info, step } = require('../core/chalk');
10
+ const { warn, info, step } = require('../core/chalk');
11
+ const { throwCommandError, throwUsage } = require('../core/command-errors');
11
12
 
12
13
  /**
13
14
  * compile 命令:只编译自定义页面源码,不发布到宜搭。
@@ -15,9 +16,9 @@ const { warn, error, info, step } = require('../core/chalk');
15
16
  */
16
17
  async function run(args) {
17
18
  if (!args || args.length < 1) {
18
- warn(t('cli.compile_usage'));
19
- warn(t('cli.compile_example'));
20
- process.exit(1);
19
+ throwUsage(t('cli.compile_usage'), t('cli.compile_example'), {
20
+ code: 'COMPILE_INVALID_ARGUMENTS',
21
+ });
21
22
  }
22
23
 
23
24
  const skipLint = args.includes('--skip-lint');
@@ -25,7 +26,10 @@ async function run(args) {
25
26
  const filteredArgs = args.filter(arg => arg !== '--skip-lint' && arg !== '--compat' && arg !== '--modern');
26
27
  let sourcePath = path.resolve(filteredArgs[0]);
27
28
  if (!fs.existsSync(sourcePath)) {
28
- error(t('publish.source_not_found', sourcePath));
29
+ throwCommandError(t('publish.source_not_found', sourcePath), {
30
+ code: 'COMPILE_SOURCE_NOT_FOUND',
31
+ details: { sourcePath },
32
+ });
29
33
  }
30
34
 
31
35
  const initialSourceCode = fs.readFileSync(sourcePath, 'utf-8');
@@ -35,7 +39,10 @@ async function run(args) {
35
39
  const buildResult = buildPageFile(sourcePath, { modern: compat, skipSizeWarning: true });
36
40
  if (!buildResult.ok) {
37
41
  buildResult.errors.forEach((issue) => warn(`${issue.code}: ${issue.message}`));
38
- process.exit(1);
42
+ throwCommandError(t('build_page.failed'), {
43
+ code: 'COMPILE_BUILD_PAGE_FAILED',
44
+ details: { errors: buildResult.errors },
45
+ });
39
46
  }
40
47
  sourcePath = buildResult.outputPath;
41
48
  info(t('build_page.output', sourcePath));
@@ -46,7 +53,10 @@ async function run(args) {
46
53
  const sourceCode = fs.readFileSync(sourcePath, 'utf-8');
47
54
  const lintPassed = runLintCheck(sourceCode, sourcePath);
48
55
  if (!lintPassed) {
49
- process.exit(1);
56
+ throwCommandError(t('check_page.failed'), {
57
+ code: 'COMPILE_LINT_FAILED',
58
+ details: { sourcePath },
59
+ });
50
60
  }
51
61
  } else {
52
62
  info(t('publish.lint_skipped'));
@@ -17,6 +17,11 @@ const { createAuthRef } = require('../core/yida-client');
17
17
  const { t } = require('../core/i18n');
18
18
  const { buildYidaI18n, normalizeYidaLocale, resolveContentLocale } = require('../core/yida-i18n');
19
19
  const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
20
+ const { throwCommandError } = require('../core/command-errors');
21
+ const {
22
+ assertLegacyDirectWriteAllowed,
23
+ extractLegacyGuardArgs,
24
+ } = require('../core/legacy-schema-guard');
20
25
  const { assertPresetThemeKey } = require('./theme-presets');
21
26
 
22
27
  const DEFAULT_APP_OPTIONS = {
@@ -280,7 +285,8 @@ function buildCreateAppPayload(params, auth, contentLocale, openExclusive, openP
280
285
 
281
286
  async function run(args) {
282
287
  const openOption = parseOpenOption(args);
283
- args = openOption.args;
288
+ const guardSplit = extractLegacyGuardArgs(openOption.args);
289
+ args = guardSplit.args;
284
290
 
285
291
  if (hasHelpFlag(args)) {
286
292
  printUsage();
@@ -300,6 +306,12 @@ async function run(args) {
300
306
  chalkError(t('create_app.usage'), { hint: t('create_app.example') });
301
307
  }
302
308
 
309
+ assertLegacyDirectWriteAllowed({
310
+ command: 'create-app',
311
+ resourceType: 'app',
312
+ action: 'create',
313
+ }, { guardOptions: guardSplit.guardOptions });
314
+
303
315
  const { appName, description, icon, iconColor, colour, navTheme, layoutDirection } = params;
304
316
 
305
317
  const { c, banner, step, label, success: chalkSuccess, result: chalkResult } = require('../core/chalk');
@@ -370,7 +382,7 @@ async function run(args) {
370
382
  const errorMsg = response ? response.errorMsg || t('common.unknown_error') : t('common.request_failed');
371
383
  chalkResult(false, t('create_app.failed', errorMsg));
372
384
  console.log(JSON.stringify({ success: false, error: errorMsg }));
373
- process.exit(1);
385
+ throwCommandError(errorMsg);
374
386
  }
375
387
  }
376
388
 
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * create-form/api-path.js
5
+ *
6
+ * 接口路径生成:构建宜搭表单设计相关的 API 请求路径。
7
+ *
8
+ * @param {string} appType 应用标识(appType)
9
+ * @param {string} apiName 接口名称(不含扩展名),如 saveFormSchema
10
+ * @param {object} [options] 可选项
11
+ * @param {string} [options.prefix] 额外的路径前缀(会以 / 拼接)
12
+ * @param {string} [options.namespace] 命名空间,默认 dingtalk
13
+ * @param {boolean} [options.addTimestamp] 是否追加 _stamp 时间戳查询参数
14
+ * @returns {string} 拼接完成的 API 请求路径
15
+ */
16
+ function buildApiPath(appType, apiName, options = {}) {
17
+ const { prefix = '', namespace = 'dingtalk', addTimestamp = false } = options;
18
+ const prefixPath = prefix ? `/${prefix}` : '';
19
+ const timestamp = addTimestamp ? `?_stamp=${Date.now()}` : '';
20
+ return `/${namespace}/web/${appType}${prefixPath}/query/formdesign/${apiName}.json${timestamp}`;
21
+ }
22
+
23
+ module.exports = {
24
+ buildApiPath,
25
+ };
@@ -85,6 +85,7 @@ function createParseArgs(dependencies) {
85
85
  labelAlign: 'top',
86
86
  contentLocale: null,
87
87
  browserOpenMode: openOption.mode,
88
+ legacyGuardOptions: openOption.legacyGuardOptions || null,
88
89
  };
89
90
 
90
91
  const args = [...rawArgs];
@@ -118,6 +119,18 @@ function createParseArgs(dependencies) {
118
119
  }
119
120
  }
120
121
 
122
+ if (args.includes('--help') || args.includes('-h')) {
123
+ usage(t('create_form.usage_create_short'));
124
+ hint(t('create_form.usage_update_short'));
125
+ hint(t('create_form.example_create'));
126
+ hint(t('create_form.example_update'));
127
+ return {
128
+ mode: 'help',
129
+ help: true,
130
+ ...options
131
+ };
132
+ }
133
+
121
134
  const mode = args[0];
122
135
 
123
136
  if (mode === 'create') {
@@ -17,7 +17,11 @@ function dispatchCreateFormCommand(parsedArgs, authContext, handlers) {
17
17
  case 'add-option':
18
18
  return handlers.addOption(...args);
19
19
  case 'create':
20
+ return handlers.create(...args);
20
21
  default:
22
+ if (parsedArgs.mode && parsedArgs.mode !== 'create') {
23
+ throw new Error('Unknown create-form mode: ' + parsedArgs.mode);
24
+ }
21
25
  return handlers.create(...args);
22
26
  }
23
27
  }
@@ -47,11 +47,11 @@ function createDefinitionReaders(dependencies) {
47
47
  } else if (typeof parsed === 'object' && parsed !== null) {
48
48
  fields = parsed.fields || [];
49
49
  columns = parsed.columns !== undefined ? parsed.columns : 1;
50
- validations = Array.isArray(parsed.validations)
51
- ? parsed.validations
52
- : Array.isArray(parsed.rules)
53
- ? parsed.rules
54
- : [];
50
+ if (Array.isArray(parsed.validations)) {
51
+ validations = parsed.validations;
52
+ } else if (Array.isArray(parsed.rules)) {
53
+ validations = parsed.rules;
54
+ }
55
55
  } else {
56
56
  throw new Error(t('create_form.fields_format_invalid'));
57
57
  }
@@ -91,14 +91,14 @@ function createDefinitionReaders(dependencies) {
91
91
  path,
92
92
  error,
93
93
  inlineObject: true,
94
- missingMessage: '补丁文件不存在: ',
94
+ missingMessage: t('create_form.patch_file_not_found'),
95
95
  });
96
96
 
97
97
  try {
98
98
  const patch = safeParseJson(rawContent);
99
99
  if (Array.isArray(patch)) {
100
100
  if (patch.length === 0) {
101
- throw new Error('补丁数组不能为空');
101
+ throw new Error(t('create_form.patch_must_not_be_empty'));
102
102
  }
103
103
  return patch;
104
104
  }
@@ -110,9 +110,9 @@ function createDefinitionReaders(dependencies) {
110
110
  return [patch];
111
111
  }
112
112
  }
113
- throw new Error('补丁必须是数组、{operations: []} 或单个操作对象');
113
+ throw new Error(t('create_form.patch_invalid_shape'));
114
114
  } catch (parseError) {
115
- error('补丁 JSON 解析失败: ' + parseError.message);
115
+ error(t('create_form.patch_parse_failed') + parseError.message);
116
116
  }
117
117
  }
118
118
 
@@ -122,21 +122,21 @@ function createDefinitionReaders(dependencies) {
122
122
  path,
123
123
  error,
124
124
  inlineObject: true,
125
- missingMessage: '规则文件不存在: ',
125
+ missingMessage: t('create_form.rule_file_not_found'),
126
126
  });
127
127
 
128
128
  try {
129
129
  const parsed = safeParseJson(rawContent);
130
130
  if (Array.isArray(parsed)) {
131
131
  if (parsed.length === 0) {
132
- throw new Error('规则数组不能为空');
132
+ throw new Error(t('create_form.rule_array_empty'));
133
133
  }
134
134
  return parsed;
135
135
  }
136
136
  if (parsed && typeof parsed === 'object') {
137
137
  if (Array.isArray(parsed.rules)) {
138
138
  if (parsed.rules.length === 0) {
139
- throw new Error('rules 数组不能为空');
139
+ throw new Error(t('create_form.rules_array_empty'));
140
140
  }
141
141
  return parsed.rules;
142
142
  }
@@ -144,9 +144,9 @@ function createDefinitionReaders(dependencies) {
144
144
  return [parsed];
145
145
  }
146
146
  }
147
- throw new Error('规则必须是数组、{rules: []} 或单个规则对象');
147
+ throw new Error(t('create_form.rule_invalid_shape'));
148
148
  } catch (parseError) {
149
- error('规则 JSON 解析失败: ' + parseError.message);
149
+ error(t('create_form.rule_parse_failed') + parseError.message);
150
150
  }
151
151
  }
152
152
 
@@ -160,27 +160,27 @@ function createDefinitionReaders(dependencies) {
160
160
  path,
161
161
  error,
162
162
  inlineObject: true,
163
- missingMessage: '校验规则文件不存在: ',
163
+ missingMessage: t('create_form.validation_file_not_found'),
164
164
  });
165
165
 
166
166
  try {
167
167
  const parsed = safeParseJson(rawContent);
168
168
  if (Array.isArray(parsed)) {
169
169
  if (parsed.length === 0) {
170
- throw new Error('校验规则数组不能为空');
170
+ throw new Error(t('create_form.validation_array_empty'));
171
171
  }
172
172
  return parsed;
173
173
  }
174
174
  if (parsed && typeof parsed === 'object') {
175
175
  if (Array.isArray(parsed.validations)) {
176
176
  if (parsed.validations.length === 0) {
177
- throw new Error('validations 数组不能为空');
177
+ throw new Error(t('create_form.validations_array_empty'));
178
178
  }
179
179
  return parsed.validations;
180
180
  }
181
181
  if (Array.isArray(parsed.rules)) {
182
182
  if (parsed.rules.length === 0) {
183
- throw new Error('rules 数组不能为空');
183
+ throw new Error(t('create_form.rules_array_empty'));
184
184
  }
185
185
  return parsed.rules;
186
186
  }
@@ -188,9 +188,9 @@ function createDefinitionReaders(dependencies) {
188
188
  return [parsed];
189
189
  }
190
190
  }
191
- throw new Error('校验规则必须是数组、{validations: []}、{rules: []} 或单个规则对象');
191
+ throw new Error(t('create_form.validation_invalid_shape'));
192
192
  } catch (parseError) {
193
- error('校验规则 JSON 解析失败: ' + parseError.message);
193
+ error(t('create_form.validation_parse_failed') + parseError.message);
194
194
  }
195
195
  }
196
196
 
@@ -200,17 +200,17 @@ function createDefinitionReaders(dependencies) {
200
200
  path,
201
201
  error,
202
202
  inlineObject: true,
203
- missingMessage: '数据源文件不存在: ',
203
+ missingMessage: t('create_form.datasource_file_not_found'),
204
204
  });
205
205
 
206
206
  try {
207
207
  const parsed = safeParseJson(rawContent);
208
208
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
209
- throw new Error('数据源配置必须是对象');
209
+ throw new Error(t('create_form.datasource_must_be_object'));
210
210
  }
211
211
  return parsed;
212
212
  } catch (parseError) {
213
- error('数据源 JSON 解析失败: ' + parseError.message);
213
+ error(t('create_form.datasource_parse_failed') + parseError.message);
214
214
  }
215
215
  }
216
216
 
@@ -26,12 +26,32 @@ function createFieldNormalizers(deps) {
26
26
  throw new Error('createFieldNormalizers requires a toDesignerValidationRule function');
27
27
  }
28
28
 
29
+ function makeOptionSid(optionIndex) {
30
+ return 'serial_' + Date.now().toString(36) + '_' + optionIndex;
31
+ }
32
+
33
+ function pickOptionValue(option, rawText) {
34
+ if (option.value !== undefined) {
35
+ return option.value;
36
+ }
37
+ if (option.id !== undefined) {
38
+ return option.id;
39
+ }
40
+ if (option.key !== undefined) {
41
+ return option.key;
42
+ }
43
+ return rawText;
44
+ }
45
+
29
46
  function buildOptionDataSource(options) {
47
+ if (!Array.isArray(options)) {
48
+ return [];
49
+ }
30
50
  return options.map(function (optionText, optionIndex) {
31
51
  return {
32
52
  text: i18n(optionText, optionText, optionText),
33
53
  value: optionText,
34
- sid: 'serial_' + Date.now().toString(36) + optionIndex,
54
+ sid: makeOptionSid(optionIndex),
35
55
  disable: false,
36
56
  defaultChecked: false,
37
57
  };
@@ -44,20 +64,18 @@ function createFieldNormalizers(deps) {
44
64
  return {
45
65
  text: i18n(optionText, optionText, optionText),
46
66
  value: optionText,
47
- sid: 'serial_' + Date.now().toString(36) + optionIndex,
67
+ sid: makeOptionSid(optionIndex),
48
68
  disable: false,
49
69
  defaultChecked: false,
50
70
  };
51
71
  }
52
72
  if (option && typeof option === 'object') {
53
73
  const rawText = option.text || option.label || option.name || option.title || option.value || '';
54
- const rawValue = option.value !== undefined ? option.value :
55
- option.id !== undefined ? option.id :
56
- option.key !== undefined ? option.key : rawText;
74
+ const rawValue = pickOptionValue(option, rawText);
57
75
  return {
58
76
  text: rawText && typeof rawText === 'object' ? rawText : i18n(String(rawText), String(rawText), String(rawText)),
59
77
  value: String(rawValue),
60
- sid: option.sid || 'serial_' + Date.now().toString(36) + optionIndex,
78
+ sid: option.sid || makeOptionSid(optionIndex),
61
79
  disable: option.disable || false,
62
80
  defaultChecked: option.defaultChecked || false,
63
81
  };
@@ -66,7 +84,7 @@ function createFieldNormalizers(deps) {
66
84
  return {
67
85
  text: i18n(fallbackText, fallbackText, fallbackText),
68
86
  value: fallbackText,
69
- sid: 'serial_' + Date.now().toString(36) + optionIndex,
87
+ sid: makeOptionSid(optionIndex),
70
88
  disable: false,
71
89
  defaultChecked: false,
72
90
  };
@@ -234,6 +252,7 @@ function createFieldNormalizers(deps) {
234
252
  unified_social_credit_code: 'unifiedSocialCreditCode',
235
253
  mail: 'email',
236
254
  e_mail: 'email',
255
+ email: 'email',
237
256
  required: 'required',
238
257
  compare: 'compare',
239
258
  crossfield: 'compare',
@@ -5,7 +5,7 @@ function decodeJsonPointerSegment(segment) {
5
5
  }
6
6
 
7
7
  function splitJsonPointer(pointer) {
8
- if (pointer === '' || pointer === '/') {
8
+ if (pointer === '') {
9
9
  return [];
10
10
  }
11
11
  if (!String(pointer).startsWith('/')) {
@@ -16,6 +16,9 @@ function splitJsonPointer(pointer) {
16
16
 
17
17
  function deepMerge(target, source) {
18
18
  Object.keys(source || {}).forEach(function (key) {
19
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
20
+ return;
21
+ }
19
22
  const value = source[key];
20
23
  if (value && typeof value === 'object' && !Array.isArray(value)) {
21
24
  if (!target[key] || typeof target[key] !== 'object' || Array.isArray(target[key])) {