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.
- package/README.md +37 -2
- package/bin/yida.js +113 -18
- package/docs/capabilities.md +202 -0
- package/lib/agent-center/agent-center.js +2 -3
- package/lib/app/app-list.js +3 -4
- package/lib/app/build-page.js +13 -6
- package/lib/app/check-page.js +16 -6
- package/lib/app/compile.js +17 -7
- package/lib/app/create-app.js +14 -2
- package/lib/app/create-form/api-path.js +25 -0
- package/lib/app/create-form/args.js +13 -0
- package/lib/app/create-form/commands.js +4 -0
- package/lib/app/create-form/definition-reader.js +23 -23
- package/lib/app/create-form/field-normalizers.js +26 -7
- package/lib/app/create-form/schema-patch.js +4 -1
- package/lib/app/create-form.js +155 -68
- package/lib/app/create-page.js +47 -10
- package/lib/app/generate-page.js +20 -1
- package/lib/app/get-form-config.js +2 -1
- package/lib/app/get-schema.js +67 -15
- package/lib/app/import-app.js +94 -42
- package/lib/app/list-forms.js +4 -8
- package/lib/app/page-ir.js +140 -0
- package/lib/app/publish.js +289 -556
- package/lib/app/schema-field-resolution.js +370 -0
- package/lib/app/services/app-reader.js +85 -0
- package/lib/app/services/app-service.js +235 -0
- package/lib/app/services/canvas-page-compiler.js +91 -0
- package/lib/app/services/canvas-page-schema-builder.js +149 -0
- package/lib/app/services/field-bindings.js +68 -0
- package/lib/app/services/form-compiler.js +1922 -0
- package/lib/app/services/form-mode-service.js +182 -0
- package/lib/app/services/form-schema-patcher.js +333 -0
- package/lib/app/services/form-schema-reader.js +59 -0
- package/lib/app/services/form-service.js +379 -0
- package/lib/app/services/form-validation.js +562 -0
- package/lib/app/services/native-page-compiler.js +92 -0
- package/lib/app/services/native-page-schema-builder.js +428 -0
- package/lib/app/services/page-resource-service.js +185 -0
- package/lib/app/update-app.js +22 -9
- package/lib/app/update-form-config.js +4 -2
- package/lib/asset/asset-cmd.js +19 -6
- package/lib/auth/oauth-loopback.js +376 -15
- package/lib/auth/token-auth.js +34 -3
- package/lib/auth/token-store.js +22 -4
- package/lib/basic-info/basic-info.js +2 -1
- package/lib/bridge/bridge.js +43 -18
- package/lib/core/agent-capabilities.js +5 -3
- package/lib/core/command-errors.js +38 -0
- package/lib/core/command-manifest.js +59 -1
- package/lib/core/copy.js +12 -0
- package/lib/core/doctor.js +15 -4
- package/lib/core/env-cmd.js +1 -1
- package/lib/core/env.js +7 -6
- package/lib/core/i18n.js +66 -8
- package/lib/core/legacy-schema-guard.js +408 -0
- package/lib/core/locales/en.js +38 -46
- package/lib/core/locales/zh.js +30 -46
- package/lib/core/sample.js +12 -2
- package/lib/core/utils.js +334 -66
- package/lib/core/yida-client.js +108 -5
- package/lib/corp-efficiency/corp-efficiency.js +2 -2
- package/lib/corp-manager/corp-manager.js +3 -3
- package/lib/formula/evaluate.js +11 -68
- package/lib/formula/field-refs.js +83 -0
- package/lib/i18n-management/i18n-management.js +2 -3
- package/lib/process/configure-process.js +44 -1992
- package/lib/process/create-process.js +54 -87
- package/lib/process/preview-process.js +20 -8
- package/lib/process/services/process-compiler.js +2056 -0
- package/lib/process/services/process-reader.js +232 -0
- package/lib/process/services/process-resource-service.js +571 -0
- package/lib/process/services/process-service.js +122 -0
- package/lib/process/services/process-stage-checkpoint.js +246 -0
- package/lib/report/append.js +7 -26
- package/lib/report/http.js +31 -5
- package/lib/report/index.js +10 -2
- package/lib/samples/yida-canvas-custom-page/business-list.canvas.jsx +63 -14
- package/lib/samples/yida-canvas-custom-page/dashboard-overview.canvas.jsx +176 -32
- package/lib/samples/yida-canvas-custom-page/dashboard-starter.canvas.jsx +5 -2
- package/lib/samples/yida-canvas-custom-page/data-management.canvas.jsx +228 -14
- package/lib/samples/yida-canvas-custom-page/portal-shell-home.canvas.jsx +2 -2
- package/lib/samples/yida-canvas-custom-page/split-pane-detail.canvas.jsx +206 -10
- package/lib/samples/yida-custom-page/data-management.oyd.jsx +14 -3
- package/lib/samples/yida-custom-page/design-tokens.js +2 -2
- package/lib/samples/yida-custom-page/detail-profile.oyd.jsx +1 -1
- package/lib/samples/yida-custom-page/portal-shell-home.oyd.jsx +7 -2
- package/lib/samples/yida-custom-page/split-pane-detail.oyd.jsx +2 -1
- package/lib/schema/adapters/app-adapter.js +210 -0
- package/lib/schema/adapters/form-adapter.js +1362 -0
- package/lib/schema/adapters/keys.js +19 -0
- package/lib/schema/adapters/page-adapter.js +566 -0
- package/lib/schema/adapters/process-adapter.js +519 -0
- package/lib/schema/applier.js +1878 -0
- package/lib/schema/apply-store.js +1083 -0
- package/lib/schema/command.js +645 -0
- package/lib/schema/dependency-graph.js +83 -0
- package/lib/schema/errors.js +481 -0
- package/lib/schema/hash.js +9 -0
- package/lib/schema/manifest-limits.js +177 -0
- package/lib/schema/manifest-loader.js +309 -0
- package/lib/schema/manifest-schema-v1.json +193 -0
- package/lib/schema/normalize-manifest.js +281 -0
- package/lib/schema/page-canvas-foundation.js +447 -0
- package/lib/schema/page-data-source-builder.js +561 -0
- package/lib/schema/page-foundation.js +556 -0
- package/lib/schema/page-source-loader.js +314 -0
- package/lib/schema/planner.js +691 -0
- package/lib/schema/remote-dispatch-boundary.js +39 -0
- package/lib/schema/remote-missing.js +21 -0
- package/lib/schema/remote-reader.js +189 -0
- package/lib/schema/resource-registry.js +157 -0
- package/lib/schema/server-revision.js +71 -0
- package/lib/schema/sort.js +28 -0
- package/lib/schema/state-store.js +589 -0
- package/package.json +10 -8
- package/scripts/check-release-risks.js +254 -0
- package/scripts/generate-command-docs.js +6 -1
- package/scripts/i18n-baseline.json +11 -11
- package/scripts/postinstall.js +8 -12
- package/scripts/validate-ci.sh +15 -11
- package/scripts/validate-i18n.js +30 -9
- package/scripts/validate-package-size.js +5 -2
- package/scripts/validate-skills.js +4 -0
- package/scripts/validate-structure.js +15 -0
- package/yida-skills/SKILL.md +117 -30
- package/yida-skills/references/schema-as-code-phase1.md +99 -0
- package/yida-skills/references/setup-and-env.md +59 -59
- package/yida-skills/references/task-retrospective.md +6 -6
- package/yida-skills/skills/yida-app/SKILL.md +78 -17
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +18 -7
- package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +3 -3
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +15 -0
- package/yida-skills/skills/yida-create-app/SKILL.md +21 -3
- package/yida-skills/skills/yida-create-form-page/SKILL.md +19 -1
- package/yida-skills/skills/yida-create-page/SKILL.md +16 -3
- package/yida-skills/skills/yida-create-process/SKILL.md +100 -4
- package/yida-skills/skills/yida-custom-page/SKILL.md +19 -4
- package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
- package/yida-skills/skills/yida-dashboard/references/pitfalls.md +1 -1
- package/yida-skills/skills/yida-get-schema/SKILL.md +49 -5
- package/yida-skills/skills/yida-i18n/SKILL.md +1 -1
- package/yida-skills/skills/yida-integration/SKILL.md +7 -1
- package/yida-skills/skills/yida-login/SKILL.md +50 -99
- package/yida-skills/skills/yida-page-config/SKILL.md +7 -1
- package/yida-skills/skills/yida-page-uiux/references/app/blueprint.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/app/navigation-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/app/role-journey.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/app-blueprint.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/chart-contracts.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/component-contracts.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/layout-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/dashboard/theme-recipes.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/detail/object-narrative.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/detail/section-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/detail/timeline-and-related.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/assets-workflow.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/industry-playbooks.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/research-levels.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/landing/section-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/drawer-detail.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/empty-loading-error.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/filter-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/list/table-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/scenes/screen.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/workbench/entry-patterns.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/workbench/portal-layouts.md +0 -1
- package/yida-skills/skills/yida-page-uiux/references/workbench/task-feed.md +0 -1
- package/yida-skills/skills/yida-page-uiux/workflow/output-decision-block.md +1 -1
- package/yida-skills/skills/yida-process-rule/SKILL.md +35 -1
- package/yida-skills/skills/yida-publish-page/SKILL.md +46 -4
- package/yida-skills/skills/yida-report/SKILL.md +9 -235
- package/yida-skills/skills/yida-report/references/schema-builder-details.md +239 -0
- package/yida-skills/skills/yida-skill-evaluator/SKILL.md +170 -0
- package/yida-skills/skills-index.json +238 -54
- package/lib/core/locales/ar.js +0 -834
- package/lib/core/locales/de.js +0 -834
- package/lib/core/locales/es.js +0 -834
- package/lib/core/locales/fr.js +0 -834
- package/lib/core/locales/hi.js +0 -834
- package/lib/core/locales/ja.js +0 -1227
- package/lib/core/locales/ko.js +0 -836
- package/lib/core/locales/pt.js +0 -834
- package/lib/core/locales/vi.js +0 -834
- package/lib/core/locales/zh-HK.js +0 -1263
- package/project/pages/src/demo-birthday-game.oyd.jsx +0 -832
- package/project/pages/src/demo-chip-insight.oyd.jsx +0 -983
- package/project/pages/src/demo-compat-smoke.oyd.jsx +0 -58
- package/project/pages/src/demo-crm-batch-entry.oyd.jsx +0 -805
- package/project/pages/src/demo-crm-dashboard.oyd.jsx +0 -677
- package/project/pages/src/demo-future-vision-2026.oyd.jsx +0 -1102
- package/project/pages/src/demo-ppt.oyd.jsx +0 -1192
- package/project/pages/src/demo-salary-calculator.oyd.jsx +0 -904
- package/project/pages/src/openyida-knowledge-doc.oyd.jsx +0 -1714
- package/yida-skills/skills/large-file-write/SKILL.md +0 -93
- package/yida-skills/skills/large-file-write/references/write-patterns.md +0 -147
- package/yida-skills/skills/large-file-write/scripts/write.js +0 -157
- package/yida-skills/skills/sls-log-workbench/SKILL.md +0 -134
- package/yida-skills/skills/sls-log-workbench/references/workbench-reference.md +0 -130
- package/yida-skills/skills/sls-log-workbench/sls-query.js +0 -295
package/lib/app/get-schema.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* get-schema.js - 宜搭表单 Schema 获取命令
|
|
3
3
|
*
|
|
4
4
|
* 用法:
|
|
5
|
+
* openyida get-schema <appType> <formUuid> [--compact] [--resolve-fields <labelOrFieldId,...>]
|
|
5
6
|
* openyida get-schema <appType> <formUuid> [--summary-json|--field-map-json]
|
|
6
7
|
* openyida get-schema <appType> --all [--summary-json] [--output-dir <dir>] [--concurrency N] [--retries N]
|
|
7
8
|
*/
|
|
@@ -18,7 +19,9 @@ const {
|
|
|
18
19
|
requestWithAutoLogin,
|
|
19
20
|
} = require('../core/utils');
|
|
20
21
|
const { t } = require('../core/i18n');
|
|
22
|
+
const { throwCommandError } = require('../core/command-errors');
|
|
21
23
|
const { fetchFormPageList } = require('./form-navigation');
|
|
24
|
+
const { buildFieldResolution } = require('./schema-field-resolution');
|
|
22
25
|
|
|
23
26
|
// 需要在报表 fieldCode 中加 _value 后缀的字段类型
|
|
24
27
|
const FIELD_TYPES_NEEDING_VALUE_SUFFIX = new Set([
|
|
@@ -201,8 +204,9 @@ function parseArgs(args) {
|
|
|
201
204
|
concurrency: 3,
|
|
202
205
|
retries: 1,
|
|
203
206
|
keyword: '',
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
compact: false,
|
|
208
|
+
fields: [],
|
|
209
|
+
// 保留已有单字段参数,作为 --fields 的单值兼容别名。
|
|
206
210
|
field: '',
|
|
207
211
|
json: false,
|
|
208
212
|
summaryJson: false,
|
|
@@ -224,7 +228,15 @@ function parseArgs(args) {
|
|
|
224
228
|
} else if (arg === '--keyword' && args[index + 1]) {
|
|
225
229
|
parsed.keyword = args[index + 1];
|
|
226
230
|
index++;
|
|
227
|
-
} else if (arg === '--
|
|
231
|
+
} else if (arg === '--compact') {
|
|
232
|
+
parsed.compact = true;
|
|
233
|
+
} else if (arg === '--resolve-fields') {
|
|
234
|
+
parsed.compact = true;
|
|
235
|
+
if (args[index + 1] && !args[index + 1].startsWith('--')) {
|
|
236
|
+
appendFieldQueries(parsed.fields, args[index + 1]);
|
|
237
|
+
index++;
|
|
238
|
+
}
|
|
239
|
+
} else if (arg === '--field' && args[index + 1] && !args[index + 1].startsWith('--')) {
|
|
228
240
|
parsed.field = args[index + 1];
|
|
229
241
|
index++;
|
|
230
242
|
} else if (arg === '--json') {
|
|
@@ -239,15 +251,27 @@ function parseArgs(args) {
|
|
|
239
251
|
return parsed;
|
|
240
252
|
}
|
|
241
253
|
|
|
254
|
+
function appendFieldQueries(target, value) {
|
|
255
|
+
String(value || '')
|
|
256
|
+
.split(/[,,]/)
|
|
257
|
+
.map(item => item.trim())
|
|
258
|
+
.filter(Boolean)
|
|
259
|
+
.forEach((item) => {
|
|
260
|
+
if (!target.includes(item)) {
|
|
261
|
+
target.push(item);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
242
266
|
function ensureUsage(parsed) {
|
|
243
267
|
if (!parsed.appType || (!parsed.all && !parsed.formUuid)) {
|
|
244
268
|
const { error: chalkError } = require('../core/chalk');
|
|
245
269
|
chalkError(t('get_schema.usage'), { hint: t('get_schema.example') });
|
|
246
270
|
}
|
|
247
|
-
//
|
|
248
|
-
if (parsed.field && parsed.all) {
|
|
271
|
+
// contract v1 的 resource 对应单个 form,不与 --all 批量模式混用。
|
|
272
|
+
if ((parsed.compact || parsed.field) && parsed.all) {
|
|
249
273
|
const { error: chalkError } = require('../core/chalk');
|
|
250
|
-
chalkError('
|
|
274
|
+
chalkError(t('get_schema.usage'), { hint: t('get_schema.example') });
|
|
251
275
|
}
|
|
252
276
|
}
|
|
253
277
|
|
|
@@ -502,21 +526,37 @@ async function runSingle(parsed, authRef) {
|
|
|
502
526
|
banner(t('get_schema.title'));
|
|
503
527
|
label('App', parsed.appType);
|
|
504
528
|
label('Form', parsed.formUuid);
|
|
505
|
-
if (parsed.field) {
|
|
529
|
+
if (parsed.field) {
|
|
530
|
+
label('Field', parsed.field);
|
|
531
|
+
} else if (parsed.fields.length > 0) {
|
|
532
|
+
label('Fields', parsed.fields.join(', '));
|
|
533
|
+
}
|
|
506
534
|
|
|
507
535
|
// Step 2: 获取表单 Schema
|
|
508
536
|
step(2, t('get_schema.step_get'));
|
|
509
537
|
info(t('get_schema.sending'));
|
|
510
538
|
|
|
511
|
-
|
|
539
|
+
let result;
|
|
540
|
+
try {
|
|
541
|
+
result = await fetchSchema(parsed.appType, parsed.formUuid, authRef);
|
|
542
|
+
} catch (error) {
|
|
543
|
+
if (!parsed.compact) {
|
|
544
|
+
throw error;
|
|
545
|
+
}
|
|
546
|
+
chalkResult(false, t('get_schema.failed', t('common.request_failed')));
|
|
547
|
+
process.exit(1);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
512
550
|
|
|
513
551
|
if (!isSuccessfulSchemaResult(result)) {
|
|
514
|
-
const errorMsg =
|
|
552
|
+
const errorMsg = parsed.compact
|
|
553
|
+
? t('common.request_failed')
|
|
554
|
+
: result ? result.errorMsg || t('common.unknown_error') : t('common.request_failed');
|
|
515
555
|
chalkResult(false, t('get_schema.failed', errorMsg));
|
|
516
|
-
|
|
556
|
+
throwCommandError(errorMsg);
|
|
517
557
|
}
|
|
518
558
|
|
|
519
|
-
// --field
|
|
559
|
+
// 保留既有 --field 返回结构;新 contract 仅由 --compact / --resolve-fields 触发。
|
|
520
560
|
if (parsed.field) {
|
|
521
561
|
const allFieldNodes = collectFieldNodes(result);
|
|
522
562
|
const aliasMaps = buildComponentAliasMaps(result);
|
|
@@ -530,18 +570,29 @@ async function runSingle(parsed, authRef) {
|
|
|
530
570
|
}
|
|
531
571
|
const props = matched.props || {};
|
|
532
572
|
const labelRaw = props.label;
|
|
533
|
-
const
|
|
573
|
+
const fieldLabel = labelRaw
|
|
534
574
|
? (typeof labelRaw === 'object' ? (labelRaw.zh_CN || labelRaw.en_US || '') : String(labelRaw))
|
|
535
575
|
: '';
|
|
536
|
-
const
|
|
576
|
+
const legacyField = {
|
|
537
577
|
componentName: matched.componentName,
|
|
538
578
|
fieldId: props.fieldId || '',
|
|
539
579
|
alias: aliasMaps.aliasByFieldId[props.fieldId] || '',
|
|
540
|
-
label,
|
|
580
|
+
label: fieldLabel,
|
|
541
581
|
props,
|
|
542
582
|
};
|
|
543
583
|
chalkSuccess(t('get_schema.success'));
|
|
544
|
-
console.log(JSON.stringify(
|
|
584
|
+
console.log(JSON.stringify(legacyField, null, 2));
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (parsed.compact) {
|
|
589
|
+
chalkSuccess(t('get_schema.success'));
|
|
590
|
+
console.log(JSON.stringify(buildFieldResolution(
|
|
591
|
+
parsed.appType,
|
|
592
|
+
parsed.formUuid,
|
|
593
|
+
result,
|
|
594
|
+
parsed.fields
|
|
595
|
+
), null, 2));
|
|
545
596
|
return;
|
|
546
597
|
}
|
|
547
598
|
|
|
@@ -630,6 +681,7 @@ module.exports = {
|
|
|
630
681
|
buildSchemaSummary,
|
|
631
682
|
buildComponentAliasMaps,
|
|
632
683
|
parseArgs,
|
|
684
|
+
appendFieldQueries,
|
|
633
685
|
filterForms,
|
|
634
686
|
mapLimit,
|
|
635
687
|
fetchSchemaRecord,
|
package/lib/app/import-app.js
CHANGED
|
@@ -15,31 +15,37 @@ const {
|
|
|
15
15
|
httpPost,
|
|
16
16
|
requestWithAutoLogin,
|
|
17
17
|
} = require('../core/utils');
|
|
18
|
-
const { createAuthRef } = require('../core/yida-client');
|
|
18
|
+
const { createAuthRef, isTokenAuthRef } = require('../core/yida-client');
|
|
19
19
|
const { t } = require('../core/i18n');
|
|
20
20
|
const { buildYidaI18n, resolveContentLocale } = require('../core/yida-i18n');
|
|
21
21
|
const { banner, step, label, success, fail, warn, info, error, result, usage, hint } = require('../core/chalk');
|
|
22
|
+
const { throwUsage } = require('../core/command-errors');
|
|
23
|
+
const { getSchemaServerRevision } = require('../schema/server-revision');
|
|
24
|
+
const {
|
|
25
|
+
assertLegacyDirectWriteAllowed,
|
|
26
|
+
extractLegacyGuardArgs,
|
|
27
|
+
} = require('../core/legacy-schema-guard');
|
|
22
28
|
|
|
23
29
|
// ── 创建新应用 ────────────────────────────────────────
|
|
24
30
|
|
|
25
31
|
async function createApp(appName, authRef) {
|
|
26
32
|
const contentLocale = resolveContentLocale({ baseUrl: authRef.baseUrl });
|
|
27
|
-
const postData = querystring.stringify({
|
|
28
|
-
appName: JSON.stringify(buildYidaI18n(appName, { en_US: appName, ja_JP: appName })),
|
|
29
|
-
description: JSON.stringify(buildYidaI18n(appName, { en_US: appName, ja_JP: appName })),
|
|
30
|
-
icon: 'xian-yingyong%%#0089FF',
|
|
31
|
-
iconUrl: 'xian-yingyong%%#0089FF',
|
|
32
|
-
colour: 'blue',
|
|
33
|
-
defaultLanguage: contentLocale,
|
|
34
|
-
openExclusive: 'n',
|
|
35
|
-
openPhysicColumn: 'n',
|
|
36
|
-
openIsolationDatabase: 'n',
|
|
37
|
-
openExclusiveUnit: 'n',
|
|
38
|
-
group: 'ALL',
|
|
39
|
-
});
|
|
40
|
-
|
|
41
33
|
const result = await requestWithAutoLogin((auth) => {
|
|
42
|
-
|
|
34
|
+
const postData = querystring.stringify({
|
|
35
|
+
_csrf_token: auth.csrfToken,
|
|
36
|
+
appName: JSON.stringify(buildYidaI18n(appName, { en_US: appName, ja_JP: appName })),
|
|
37
|
+
description: JSON.stringify(buildYidaI18n(appName, { en_US: appName, ja_JP: appName })),
|
|
38
|
+
icon: 'xian-yingyong%%#0089FF',
|
|
39
|
+
iconUrl: 'xian-yingyong%%#0089FF',
|
|
40
|
+
colour: 'blue',
|
|
41
|
+
defaultLanguage: contentLocale,
|
|
42
|
+
openExclusive: 'n',
|
|
43
|
+
openPhysicColumn: 'n',
|
|
44
|
+
openIsolationDatabase: 'n',
|
|
45
|
+
openExclusiveUnit: 'n',
|
|
46
|
+
group: 'ALL',
|
|
47
|
+
});
|
|
48
|
+
return httpPost(auth.baseUrl, '/query/app/registerApp.json', postData, auth.cookies);
|
|
43
49
|
}, authRef);
|
|
44
50
|
|
|
45
51
|
if (!result || !result.success || !result.content) {
|
|
@@ -57,22 +63,30 @@ function normalizeImportFormType(formType) {
|
|
|
57
63
|
return normalized;
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
function
|
|
61
|
-
return
|
|
66
|
+
function buildCreateFormPayload(formTitle, formType = 'receipt') {
|
|
67
|
+
return {
|
|
62
68
|
formType: normalizeImportFormType(formType),
|
|
63
69
|
title: JSON.stringify(buildYidaI18n(formTitle, { en_US: formTitle, ja_JP: formTitle })),
|
|
64
|
-
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function buildCreateFormPostData(formTitle, formType = 'receipt') {
|
|
74
|
+
return querystring.stringify(buildCreateFormPayload(formTitle, formType));
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
// ── 创建空白表单/页面/报表 ──────────────────────────────
|
|
68
78
|
|
|
69
79
|
async function createBlankForm(appType, formTitle, authRef, formType = 'receipt') {
|
|
70
|
-
const postData = buildCreateFormPostData(formTitle, formType);
|
|
71
80
|
const result = await requestWithAutoLogin((auth) => {
|
|
81
|
+
const postData = querystring.stringify({
|
|
82
|
+
_csrf_token: auth.csrfToken,
|
|
83
|
+
...buildCreateFormPayload(formTitle, formType),
|
|
84
|
+
});
|
|
72
85
|
return httpPost(
|
|
73
86
|
auth.baseUrl,
|
|
74
87
|
`/dingtalk/web/${appType}/query/formdesign/saveFormSchemaInfo.json`,
|
|
75
|
-
postData
|
|
88
|
+
postData,
|
|
89
|
+
auth.cookies
|
|
76
90
|
);
|
|
77
91
|
}, authRef);
|
|
78
92
|
|
|
@@ -86,44 +100,72 @@ async function createBlankForm(appType, formTitle, authRef, formType = 'receipt'
|
|
|
86
100
|
|
|
87
101
|
// ── 保存表单 Schema ───────────────────────────────────
|
|
88
102
|
|
|
89
|
-
async function saveFormSchema(appType, formUuid, schema, authRef, formType = 'receipt') {
|
|
103
|
+
async function saveFormSchema(appType, formUuid, schema, authRef, formType = 'receipt', serverRevision) {
|
|
104
|
+
const tokenReady = isTokenAuthRef(authRef);
|
|
105
|
+
const cookieReady = !!(
|
|
106
|
+
authRef &&
|
|
107
|
+
typeof authRef.csrfToken === 'string' &&
|
|
108
|
+
authRef.csrfToken &&
|
|
109
|
+
Array.isArray(authRef.cookies)
|
|
110
|
+
);
|
|
111
|
+
if (!authRef || !authRef.baseUrl || (!tokenReady && !cookieReady)) {
|
|
112
|
+
const err = new Error('Import schema save requires an authenticated request context.');
|
|
113
|
+
err.code = 'IMPORT_SCHEMA_WRITE_PRECHECK_FAILED';
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
if (!schema || typeof schema !== 'object' || !Array.isArray(schema.pages)) {
|
|
117
|
+
const err = new Error('Imported schema content must include a pages array before writing.');
|
|
118
|
+
err.code = 'SCHEMA_REMOTE_READ_FAILED';
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
if (!Number.isFinite(serverRevision) || serverRevision < 0) {
|
|
122
|
+
const err = new Error('Imported schema revision is missing or invalid.');
|
|
123
|
+
err.code = 'SCHEMA_REMOTE_READ_FAILED';
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
|
|
90
127
|
const payload = {
|
|
91
128
|
appType,
|
|
92
129
|
formUuid,
|
|
93
130
|
content: JSON.stringify(schema),
|
|
94
131
|
schemaVersion: 'V5',
|
|
132
|
+
gmtModified: serverRevision,
|
|
95
133
|
};
|
|
96
134
|
if (normalizeImportFormType(formType) === 'report') {
|
|
97
135
|
payload.importSchema = 'true';
|
|
98
136
|
}
|
|
99
|
-
const postData = querystring.stringify(payload);
|
|
100
|
-
|
|
101
|
-
const result = await requestWithAutoLogin((auth) => {
|
|
102
|
-
return httpPost(
|
|
103
|
-
auth.baseUrl,
|
|
104
|
-
`/alibaba/web/${appType}/_view/query/formdesign/saveFormSchema.json`,
|
|
105
|
-
postData
|
|
106
|
-
);
|
|
107
|
-
}, authRef);
|
|
108
137
|
|
|
109
|
-
|
|
138
|
+
const postData = querystring.stringify(Object.assign(
|
|
139
|
+
{},
|
|
140
|
+
authRef.csrfToken ? { _csrf_token: authRef.csrfToken } : {},
|
|
141
|
+
payload
|
|
142
|
+
));
|
|
143
|
+
const authOptions = { projectRoot: authRef.projectRoot };
|
|
144
|
+
return httpPost(
|
|
145
|
+
authRef.baseUrl,
|
|
146
|
+
`/alibaba/web/${appType}/_view/query/formdesign/saveFormSchema.json`,
|
|
147
|
+
postData,
|
|
148
|
+
Array.isArray(authRef.cookies) ? authRef.cookies : authOptions,
|
|
149
|
+
Array.isArray(authRef.cookies) ? authOptions : undefined
|
|
150
|
+
);
|
|
110
151
|
}
|
|
111
152
|
|
|
112
153
|
// ── 更新表单配置(发布表单)─────────────────────────────
|
|
113
154
|
|
|
114
155
|
async function updateFormConfig(appType, formUuid, authRef) {
|
|
115
|
-
const postData = querystring.stringify({
|
|
116
|
-
appType,
|
|
117
|
-
formUuid,
|
|
118
|
-
setting: JSON.stringify({ MINI_RESOURCE: 0 }),
|
|
119
|
-
version: 1,
|
|
120
|
-
});
|
|
121
|
-
|
|
122
156
|
const result = await requestWithAutoLogin((auth) => {
|
|
157
|
+
const postData = querystring.stringify({
|
|
158
|
+
_csrf_token: auth.csrfToken,
|
|
159
|
+
appType,
|
|
160
|
+
formUuid,
|
|
161
|
+
setting: JSON.stringify({ MINI_RESOURCE: 0 }),
|
|
162
|
+
version: 1,
|
|
163
|
+
});
|
|
123
164
|
return httpPost(
|
|
124
165
|
auth.baseUrl,
|
|
125
166
|
`/dingtalk/web/${appType}/query/formdesign/updateFormConfig.json`,
|
|
126
|
-
postData
|
|
167
|
+
postData,
|
|
168
|
+
auth.cookies
|
|
127
169
|
);
|
|
128
170
|
}, authRef);
|
|
129
171
|
|
|
@@ -177,11 +219,13 @@ function extractSchemaContent(schemaResult) {
|
|
|
177
219
|
// ── 主逻辑 ────────────────────────────────────────────
|
|
178
220
|
|
|
179
221
|
async function run(args) {
|
|
222
|
+
const guardSplit = extractLegacyGuardArgs(args || []);
|
|
223
|
+
args = guardSplit.args;
|
|
180
224
|
if (args.length < 1) {
|
|
181
225
|
usage(t('import.usage'));
|
|
182
226
|
hint(t('import.example1'));
|
|
183
227
|
hint(t('import.example2'));
|
|
184
|
-
|
|
228
|
+
throwUsage(t('import.usage'), `${t('import.example1')}\n${t('import.example2')}`);
|
|
185
229
|
}
|
|
186
230
|
|
|
187
231
|
const exportFilePath = path.resolve(args[0]);
|
|
@@ -215,6 +259,11 @@ async function run(args) {
|
|
|
215
259
|
step(2, t('common.step_login_label'));
|
|
216
260
|
const authRef = createAuthRef();
|
|
217
261
|
success(t('common.login_ready', authRef.baseUrl));
|
|
262
|
+
assertLegacyDirectWriteAllowed({
|
|
263
|
+
command: 'import-app',
|
|
264
|
+
resourceType: 'app',
|
|
265
|
+
action: 'create',
|
|
266
|
+
}, { guardOptions: guardSplit.guardOptions });
|
|
218
267
|
|
|
219
268
|
step(3, t('import.step_create_app'));
|
|
220
269
|
let newAppType;
|
|
@@ -287,9 +336,10 @@ async function run(args) {
|
|
|
287
336
|
oldFormUuid,
|
|
288
337
|
newFormUuid
|
|
289
338
|
);
|
|
339
|
+
const serverRevision = getSchemaServerRevision(formSchemaResult);
|
|
290
340
|
|
|
291
341
|
// 4.3 保存 Schema
|
|
292
|
-
const saveResult = await saveFormSchema(newAppType, newFormUuid, adaptedSchema, authRef, formType);
|
|
342
|
+
const saveResult = await saveFormSchema(newAppType, newFormUuid, adaptedSchema, authRef, formType, serverRevision);
|
|
293
343
|
if (!saveResult || !saveResult.success) {
|
|
294
344
|
const errorMsg = saveResult ? saveResult.errorMsg || t('common.unknown_error') : t('common.request_failed');
|
|
295
345
|
fail(t('import.save_schema_failed', errorMsg));
|
|
@@ -368,7 +418,9 @@ module.exports = {
|
|
|
368
418
|
run,
|
|
369
419
|
__test__: {
|
|
370
420
|
normalizeImportFormType,
|
|
421
|
+
buildCreateFormPayload,
|
|
371
422
|
buildCreateFormPostData,
|
|
423
|
+
saveFormSchema,
|
|
372
424
|
adaptSchemaIdentifiers,
|
|
373
425
|
extractSchemaContent,
|
|
374
426
|
},
|
package/lib/app/list-forms.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { createAuthRef, isAuthRefReady } = require('../core/yida-client');
|
|
4
4
|
const { t } = require('../core/i18n');
|
|
5
5
|
const { fetchFormPageList } = require('./form-navigation');
|
|
6
|
+
const { throwCommandError, throwUsage } = require('../core/command-errors');
|
|
6
7
|
|
|
7
8
|
function parseArgs(args) {
|
|
8
9
|
const parsed = {
|
|
@@ -40,10 +41,7 @@ function filterForms(forms, keyword) {
|
|
|
40
41
|
async function run(args) {
|
|
41
42
|
const parsed = parseArgs(args);
|
|
42
43
|
if (!parsed.appType) {
|
|
43
|
-
|
|
44
|
-
console.error(t('list_forms.example1'));
|
|
45
|
-
console.error(t('list_forms.example2'));
|
|
46
|
-
process.exit(1);
|
|
44
|
+
throwUsage(t('list_forms.usage'), `${t('list_forms.example1')}\n${t('list_forms.example2')}`);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
const SEP = '='.repeat(50);
|
|
@@ -58,8 +56,7 @@ async function run(args) {
|
|
|
58
56
|
console.error(t('common.step_login', 1));
|
|
59
57
|
const authRef = createAuthRef();
|
|
60
58
|
if (!isAuthRefReady(authRef)) {
|
|
61
|
-
|
|
62
|
-
process.exit(1);
|
|
59
|
+
throwCommandError(t('list_forms.no_login'), { code: 'CLI_AUTH_REQUIRED' });
|
|
63
60
|
}
|
|
64
61
|
console.error(t('common.login_ready', authRef.baseUrl));
|
|
65
62
|
|
|
@@ -68,8 +65,7 @@ async function run(args) {
|
|
|
68
65
|
try {
|
|
69
66
|
forms = await fetchFormPageList(parsed.appType, authRef);
|
|
70
67
|
} catch (error) {
|
|
71
|
-
|
|
72
|
-
process.exit(1);
|
|
68
|
+
throwCommandError(t('list_forms.failed', error.message));
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
const filteredForms = filterForms(forms, parsed.keyword);
|
package/lib/app/page-ir.js
CHANGED
|
@@ -1168,6 +1168,137 @@ function normalizeMediaAssets(spec, defaults) {
|
|
|
1168
1168
|
};
|
|
1169
1169
|
}
|
|
1170
1170
|
|
|
1171
|
+
function hasValue(value) {
|
|
1172
|
+
if (Array.isArray(value)) {
|
|
1173
|
+
return value.some(hasValue);
|
|
1174
|
+
}
|
|
1175
|
+
if (isPlainObject(value)) {
|
|
1176
|
+
return Object.keys(value).some((key) => hasValue(value[key]));
|
|
1177
|
+
}
|
|
1178
|
+
return value !== undefined && value !== null && String(value).trim() !== '';
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
function hasBlockItems(block) {
|
|
1182
|
+
return Boolean(block && Array.isArray(block.items) && block.items.some(hasValue));
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
function isSameJson(a, b) {
|
|
1186
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
function normalizeDomainSpecificity(rawSpec, options, blocks, defaults, normalized, scene) {
|
|
1190
|
+
const spec = isPlainObject(rawSpec) ? rawSpec : {};
|
|
1191
|
+
const optionInputs = isPlainObject(options) ? options : {};
|
|
1192
|
+
const heroBlock = blocks.heroBlock || {};
|
|
1193
|
+
const featureBlock = blocks.featureBlock || {};
|
|
1194
|
+
const metricBlock = blocks.metricBlock || {};
|
|
1195
|
+
const roadmapBlock = blocks.roadmapBlock || {};
|
|
1196
|
+
const ctaBlock = blocks.ctaBlock || {};
|
|
1197
|
+
const sampleFallbacks = [];
|
|
1198
|
+
const missing = [];
|
|
1199
|
+
|
|
1200
|
+
const hasDomainText = hasValue([
|
|
1201
|
+
spec.requirement,
|
|
1202
|
+
spec.requirements,
|
|
1203
|
+
spec.prompt,
|
|
1204
|
+
spec.goal,
|
|
1205
|
+
spec.industry,
|
|
1206
|
+
spec.businessType,
|
|
1207
|
+
spec.business_type,
|
|
1208
|
+
spec.name,
|
|
1209
|
+
spec.title,
|
|
1210
|
+
spec.brandName,
|
|
1211
|
+
spec.appName,
|
|
1212
|
+
spec.appBlueprint,
|
|
1213
|
+
spec.app_blueprint,
|
|
1214
|
+
]);
|
|
1215
|
+
const provided = {
|
|
1216
|
+
hero: hasValue(spec.brandName || spec.tagline || spec.heroText || heroBlock.brandName || heroBlock.tagline || heroBlock.text || heroBlock.heroText),
|
|
1217
|
+
features: hasValue(spec.features) || hasBlockItems(featureBlock),
|
|
1218
|
+
metrics: hasValue(spec.metrics) || hasBlockItems(metricBlock),
|
|
1219
|
+
roadmap: hasValue(spec.roadmap) || hasBlockItems(roadmapBlock),
|
|
1220
|
+
cta: hasValue(spec.ctaTitle || spec.ctaText || ctaBlock.title || ctaBlock.text),
|
|
1221
|
+
visualProfile: hasValue(optionInputs.visualProfile || spec.visualProfile || spec.visual_profile || spec.visual),
|
|
1222
|
+
appBlueprint: hasValue(optionInputs.appBlueprint || spec.appBlueprint || spec.app_blueprint || spec.pages || spec.roles || spec.navigation || spec.navGroups),
|
|
1223
|
+
interactionProfile: hasValue(optionInputs.interactionProfile || spec.interactionProfile || spec.interaction_profile || spec.interactions || spec.primaryAction || spec.detailMode || spec.bulkActions),
|
|
1224
|
+
insights: hasValue(optionInputs.insights || spec.insights || spec.insight),
|
|
1225
|
+
dataBinding: hasValue(optionInputs.dataBinding || spec.dataBinding || spec.data_binding || spec.formUuid || spec.form_uuid || spec.dataUrl || spec.data_url),
|
|
1226
|
+
assets: hasValue(spec.assets || spec.heroImage || spec.hero_image || spec.productImages || spec.images),
|
|
1227
|
+
};
|
|
1228
|
+
|
|
1229
|
+
if (normalized.meta.brandName === defaults.meta.brandName) {
|
|
1230
|
+
sampleFallbacks.push('brandName');
|
|
1231
|
+
}
|
|
1232
|
+
if (normalized.meta.tagline === defaults.meta.tagline) {
|
|
1233
|
+
sampleFallbacks.push('tagline');
|
|
1234
|
+
}
|
|
1235
|
+
if (normalized.meta.heroText === defaults.meta.heroText) {
|
|
1236
|
+
sampleFallbacks.push('heroText');
|
|
1237
|
+
}
|
|
1238
|
+
if (isSameJson(normalized.features, defaults.features)) {
|
|
1239
|
+
sampleFallbacks.push('features');
|
|
1240
|
+
}
|
|
1241
|
+
if (isSameJson(normalized.metrics, defaults.metrics)) {
|
|
1242
|
+
sampleFallbacks.push('metrics');
|
|
1243
|
+
}
|
|
1244
|
+
if (isSameJson(normalized.roadmap, defaults.roadmap)) {
|
|
1245
|
+
sampleFallbacks.push('roadmap');
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
if (!provided.hero) {
|
|
1249
|
+
missing.push('页面名称、业务定位和首屏说明');
|
|
1250
|
+
}
|
|
1251
|
+
if (!provided.features) {
|
|
1252
|
+
missing.push('业务对象/模块,而不是模板卖点');
|
|
1253
|
+
}
|
|
1254
|
+
if (!provided.metrics && ['dashboard', 'screen', 'workbench'].includes(scene)) {
|
|
1255
|
+
missing.push('贴合业务的指标口径');
|
|
1256
|
+
}
|
|
1257
|
+
if (!provided.roadmap && scene !== 'landing') {
|
|
1258
|
+
missing.push('用户动作、处理路径或运营节奏');
|
|
1259
|
+
}
|
|
1260
|
+
if (!provided.interactionProfile && ['dashboard', 'list', 'detail', 'workbench'].includes(scene)) {
|
|
1261
|
+
missing.push('主操作、下钻方式、筛选/批量动作和空载错状态');
|
|
1262
|
+
}
|
|
1263
|
+
if (!provided.visualProfile) {
|
|
1264
|
+
missing.push('区别于 sample 的视觉方向');
|
|
1265
|
+
}
|
|
1266
|
+
if (scene === 'landing' && !provided.assets) {
|
|
1267
|
+
missing.push('真实素材或素材缺口说明');
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
const weightedProvided = [
|
|
1271
|
+
provided.hero,
|
|
1272
|
+
provided.features,
|
|
1273
|
+
provided.metrics,
|
|
1274
|
+
provided.roadmap,
|
|
1275
|
+
provided.cta,
|
|
1276
|
+
provided.visualProfile,
|
|
1277
|
+
provided.appBlueprint,
|
|
1278
|
+
provided.interactionProfile,
|
|
1279
|
+
provided.insights,
|
|
1280
|
+
provided.dataBinding,
|
|
1281
|
+
provided.assets,
|
|
1282
|
+
].filter(Boolean).length;
|
|
1283
|
+
const score = Math.round((weightedProvided / 11) * 100);
|
|
1284
|
+
const status = sampleFallbacks.length === 0 && missing.length <= 1
|
|
1285
|
+
? 'domain-ready'
|
|
1286
|
+
: hasDomainText
|
|
1287
|
+
? 'draft-needs-domain-spec'
|
|
1288
|
+
: 'sample-reference';
|
|
1289
|
+
|
|
1290
|
+
return {
|
|
1291
|
+
status,
|
|
1292
|
+
score,
|
|
1293
|
+
sampleFallbacks,
|
|
1294
|
+
missing,
|
|
1295
|
+
provided,
|
|
1296
|
+
guidance: status === 'domain-ready'
|
|
1297
|
+
? 'Spec 已覆盖主要业务语义;sample 仅作为编译骨架。'
|
|
1298
|
+
: '补齐业务对象、指标口径、用户动作、视觉方向和素材/数据约束后再视为真实业务页;sample 只能作为可编译参考。',
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1171
1302
|
function normalizeTodoItems(items, fallback) {
|
|
1172
1303
|
const normalized = toList(items)
|
|
1173
1304
|
.filter(isPlainObject)
|
|
@@ -1228,6 +1359,14 @@ function normalizeProductHomepageSpec(rawSpec, options, templateName = PRODUCT_H
|
|
|
1228
1359
|
roadmapBlock.items || spec.roadmap,
|
|
1229
1360
|
defaults.roadmap
|
|
1230
1361
|
);
|
|
1362
|
+
const domainFidelity = normalizeDomainSpecificity(
|
|
1363
|
+
spec,
|
|
1364
|
+
options,
|
|
1365
|
+
{ heroBlock, featureBlock, metricBlock, roadmapBlock, ctaBlock },
|
|
1366
|
+
defaults,
|
|
1367
|
+
{ meta, features, metrics, roadmap },
|
|
1368
|
+
scene
|
|
1369
|
+
);
|
|
1231
1370
|
|
|
1232
1371
|
return {
|
|
1233
1372
|
irVersion: IR_VERSION,
|
|
@@ -1243,6 +1382,7 @@ function normalizeProductHomepageSpec(rawSpec, options, templateName = PRODUCT_H
|
|
|
1243
1382
|
appBlueprint,
|
|
1244
1383
|
interactionProfile,
|
|
1245
1384
|
dataBinding,
|
|
1385
|
+
domainFidelity,
|
|
1246
1386
|
meta,
|
|
1247
1387
|
assets,
|
|
1248
1388
|
insights,
|