openyida 2026.9.3 → 2026.9.4
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 +9 -4
- package/bin/yida.js +6 -0
- package/lib/app/canvas-compile.js +2 -0
- package/lib/app/create-app.js +11 -115
- package/lib/app/create-form/batch.js +204 -0
- package/lib/app/create-form.js +1 -0
- package/lib/app/inline-css-guard.js +79 -0
- package/lib/app/page-linter.js +162 -0
- package/lib/app/services/canvas-page-schema-builder.js +18 -5
- package/lib/app/theme-from-design.js +88 -0
- package/lib/app/theme-presets.js +7 -0
- package/lib/app/update-app.js +103 -43
- package/lib/core/agent-capabilities.js +14 -0
- package/lib/core/command-manifest.js +87 -10
- package/lib/core/locales/en.js +19 -6
- package/lib/core/locales/zh.js +19 -6
- package/lib/core/query-data.js +31 -9
- package/lib/core/sample.js +80 -5
- package/lib/design-plan/design-plan.js +92 -0
- package/lib/design-plan/files.js +73 -0
- package/lib/design-plan/init.js +112 -0
- package/lib/design-plan/materialize.js +898 -0
- package/lib/design-plan/normalize.js +275 -0
- package/lib/design-plan/parallel.js +56 -0
- package/lib/design-plan/patch.js +174 -0
- package/lib/design-plan/preview.js +154 -0
- package/lib/design-plan/validate.js +133 -0
- package/lib/samples/openyida-scaffold/canvas-dialog.canvas.jsx +124 -0
- package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +265 -68
- package/lib/samples/openyida-scaffold/canvas-nav/data.jsx +60 -0
- package/lib/samples/openyida-scaffold/canvas-nav/dock.jsx +13 -0
- package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +34 -0
- package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +43 -0
- package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +19 -0
- package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +96 -0
- package/lib/samples/openyida-scaffold/canvas-nav/tabs.jsx +31 -0
- package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +31 -0
- package/lib/samples/yida-canvas-table-form/table-form-batch-submit.canvas.jsx +2 -1
- package/lib/samples/yida-rechart/trend-combo.canvas.jsx +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +5 -3
- package/yida-skills/SKILL.md +37 -6
- package/yida-skills/references/field-and-url-reference.md +11 -1
- package/yida-skills/skills/yida-app/SKILL.md +42 -7
- package/yida-skills/skills/yida-app/references/common-issues.md +1 -1
- package/yida-skills/skills/yida-app/workflow/incremental-preview.md +42 -0
- package/yida-skills/skills/yida-app/workflow/parallel-work.md +69 -0
- package/yida-skills/skills/yida-app/workflow/plan/step-1-understand.md +5 -0
- package/yida-skills/skills/yida-app/workflow/plan/step-2-confirm.md +7 -0
- package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +69 -0
- package/yida-skills/skills/yida-app/workflow/plan/workflow.md +45 -0
- package/yida-skills/skills/yida-app/workflow/step-1-resource-context.md +2 -0
- package/yida-skills/skills/yida-app/workflow/step-2-design.md +24 -26
- package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +24 -7
- package/yida-skills/skills/yida-app/workflow/step-4-forms-processes.md +8 -2
- package/yida-skills/skills/yida-app/workflow/step-6-main-page.md +2 -0
- package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +12 -4
- package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +20 -10
- package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +8 -4
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +9 -6
- package/yida-skills/skills/yida-canvas-custom-page/references/canvas-authoring-examples.md +1 -1
- package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +55 -38
- package/yida-skills/skills/yida-canvas-custom-page/references/dialog-guide.md +35 -0
- package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +45 -93
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +6 -0
- package/yida-skills/skills/yida-canvas-table-form/SKILL.md +2 -2
- package/yida-skills/skills/yida-create-app/SKILL.md +33 -23
- package/yida-skills/skills/yida-create-form-page/SKILL.md +4 -0
- package/yida-skills/skills/yida-create-form-page/references/batch-forms.md +55 -0
- package/yida-skills/skills/yida-create-page/SKILL.md +2 -0
- package/yida-skills/skills/yida-custom-page/references/coding-guide.md +2 -0
- package/yida-skills/skills/yida-design/SKILL.md +31 -36
- package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +187 -0
- package/yida-skills/skills/yida-design/references/design-mode.md +14 -0
- package/yida-skills/skills/yida-design/references/style-design-selection.md +3 -3
- package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +9 -1
- package/yida-skills/skills/yida-design/references/theme/theme-token-presets.md +43 -1
- package/yida-skills/skills/yida-design/references/visual-scaffold-recipes.md +1 -0
- package/yida-skills/skills/yida-design/sub_skill/page-design/SKILL.md +2 -2
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +26 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/agents/openai.yaml +4 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/README.md +214 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/build-plan-template.html +1181 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/business-flows.png +0 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/data-models.png +0 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/form-normal.svg +4 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/form-process.svg +6 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/graph-fit.svg +3 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/graph-relations.svg +7 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/graph-zoom-in.svg +4 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/graph-zoom-out.svg +4 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/overview.png +0 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/pages.png +0 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/icons/visual-style.png +0 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +138 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +456 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/page-patterns.md +204 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +137 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +168 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +1172 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/validate_design_themes.py +190 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/README.md +98 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-media-grid.md +339 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-modular-clarity.md +348 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-structured-clarity.md +344 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ambient-halo-layered.md +345 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-focus-layered.md +355 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-luminous-modular.md +377 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/deep-stage-duotone.md +352 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/hairline-runway-clarity.md +389 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/high-contrast-modular.md +364 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/index.json +329 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/interlocked-vivid-modules.md +348 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/matrix-grid-focus.md +345 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/media-rail-inspector.md +379 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mist-layered-signal.md +347 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/modular-rail-signal.md +352 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mono-grid-signal.md +386 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ribbon-ledger-lift.md +384 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/segmented-meter-clarity.md +388 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/split-rail-precision.md +341 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/status-framed-media-grid.md +361 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/page-patterns/index.json +63 -0
- package/yida-skills/skills/yida-design/workflow/output-design.md +39 -5
- package/yida-skills/skills/yida-design/workflow/output-prd.md +1 -1
- package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +3 -3
- package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +7 -11
- package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +6 -0
- package/yida-skills/skills/yida-design/workflow/step-5-visual-states.md +3 -3
- package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +4 -4
- package/yida-skills/skills/yida-nav-group/SKILL.md +1 -0
- package/yida-skills/skills/yida-nav-shell/SKILL.md +21 -18
- package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +212 -266
- package/yida-skills/skills/yida-prd/SKILL.md +21 -32
- package/yida-skills/skills/yida-prd/references/plan-content.md +169 -0
- package/yida-skills/skills/yida-prd/workflow/output-prd.md +36 -8
- package/yida-skills/skills/yida-prd/workflow/plan-business.md +12 -0
- package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +7 -3
- package/yida-skills/skills/yida-publish-page/SKILL.md +1 -1
- package/yida-skills/skills/yida-requirement-analysis/SKILL.md +17 -19
- package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +65 -0
- package/yida-skills/skills-index.json +11 -10
- package/yida-skills/skills/yida-prd/workflow/step-1-read-brief.md +0 -15
package/lib/app/page-linter.js
CHANGED
|
@@ -15,6 +15,7 @@ const THEN_CALLBACK_LINE_LIMIT = 50;
|
|
|
15
15
|
const CALLBACK_SCAN_LINE_LIMIT = 80;
|
|
16
16
|
const parser = Babel.packages.parser;
|
|
17
17
|
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
18
|
+
const FORBIDDEN_SEARCH_FORM_DYNAMIC_ORDER_FIELDS = new Set(['gmtCreate']);
|
|
18
19
|
|
|
19
20
|
const PARSER_OPTIONS = {
|
|
20
21
|
sourceType: 'module',
|
|
@@ -404,6 +405,142 @@ function getNodeLine(node) {
|
|
|
404
405
|
return node && node.loc && node.loc.start && node.loc.start.line ? node.loc.start.line : 1;
|
|
405
406
|
}
|
|
406
407
|
|
|
408
|
+
function getStaticPropertyName(property) {
|
|
409
|
+
if (!property || (property.type !== 'ObjectProperty' && property.type !== 'ObjectMethod')) {
|
|
410
|
+
return '';
|
|
411
|
+
}
|
|
412
|
+
const key = property.key;
|
|
413
|
+
if (!key) {
|
|
414
|
+
return '';
|
|
415
|
+
}
|
|
416
|
+
if (key.type === 'Identifier' && !property.computed) {
|
|
417
|
+
return key.name;
|
|
418
|
+
}
|
|
419
|
+
if (key.type === 'StringLiteral') {
|
|
420
|
+
return key.value;
|
|
421
|
+
}
|
|
422
|
+
return '';
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function getMemberPropertyName(member) {
|
|
426
|
+
if (!member || (member.type !== 'MemberExpression' && member.type !== 'OptionalMemberExpression') || !member.property) {
|
|
427
|
+
return '';
|
|
428
|
+
}
|
|
429
|
+
if (member.property.type === 'Identifier' && !member.computed) {
|
|
430
|
+
return member.property.name;
|
|
431
|
+
}
|
|
432
|
+
if (member.property.type === 'StringLiteral') {
|
|
433
|
+
return member.property.value;
|
|
434
|
+
}
|
|
435
|
+
return '';
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function getStaticStringValue(node) {
|
|
439
|
+
if (!node) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
if (node.type === 'StringLiteral') {
|
|
443
|
+
return node.value;
|
|
444
|
+
}
|
|
445
|
+
if (node.type === 'TemplateLiteral' && node.expressions.length === 0) {
|
|
446
|
+
return node.quasis.map(part => part.value.cooked || '').join('');
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function unwrapJsonStringify(node) {
|
|
452
|
+
if (!node || node.type !== 'CallExpression' || !node.callee || node.callee.type !== 'MemberExpression') {
|
|
453
|
+
return node;
|
|
454
|
+
}
|
|
455
|
+
const object = node.callee.object;
|
|
456
|
+
if (object && object.type === 'Identifier' && object.name === 'JSON' && getMemberPropertyName(node.callee) === 'stringify') {
|
|
457
|
+
return node.arguments && node.arguments[0] ? node.arguments[0] : node;
|
|
458
|
+
}
|
|
459
|
+
return node;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function resolveStaticBinding(node, pathRef) {
|
|
463
|
+
if (!node || node.type !== 'Identifier' || !pathRef || !pathRef.scope) {
|
|
464
|
+
return node;
|
|
465
|
+
}
|
|
466
|
+
const binding = pathRef.scope.getBinding(node.name);
|
|
467
|
+
if (!binding || !binding.constant || !binding.path || binding.path.node.type !== 'VariableDeclarator') {
|
|
468
|
+
return node;
|
|
469
|
+
}
|
|
470
|
+
return binding.path.node.init || node;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function findForbiddenDynamicOrderFields(node, pathRef) {
|
|
474
|
+
const resolved = resolveStaticBinding(node, pathRef);
|
|
475
|
+
const value = resolveStaticBinding(unwrapJsonStringify(resolved), pathRef);
|
|
476
|
+
if (value && value.type === 'ObjectExpression') {
|
|
477
|
+
return value.properties
|
|
478
|
+
.map(getStaticPropertyName)
|
|
479
|
+
.filter(field => FORBIDDEN_SEARCH_FORM_DYNAMIC_ORDER_FIELDS.has(field));
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const staticValue = getStaticStringValue(value);
|
|
483
|
+
if (staticValue === null) {
|
|
484
|
+
return [];
|
|
485
|
+
}
|
|
486
|
+
try {
|
|
487
|
+
const parsed = JSON.parse(staticValue);
|
|
488
|
+
if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') {
|
|
489
|
+
return [];
|
|
490
|
+
}
|
|
491
|
+
return Object.keys(parsed).filter(field => FORBIDDEN_SEARCH_FORM_DYNAMIC_ORDER_FIELDS.has(field));
|
|
492
|
+
} catch {
|
|
493
|
+
return [];
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function findDynamicOrderProperty(params) {
|
|
498
|
+
if (!params || params.type !== 'ObjectExpression') {
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
return params.properties.find(property => getStaticPropertyName(property) === 'dynamicOrder') || null;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function reportForbiddenDynamicOrderValue(pathRef, value, issueNode, errors, disableMap) {
|
|
505
|
+
const forbiddenFields = findForbiddenDynamicOrderFields(value, pathRef);
|
|
506
|
+
if (forbiddenFields.length === 0) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
pushIssue(
|
|
510
|
+
errors,
|
|
511
|
+
getNodeLine(issueNode),
|
|
512
|
+
'searchformdata-dynamic-order-metadata',
|
|
513
|
+
t('publish.lint_searchformdata_dynamic_order_metadata', forbiddenFields.join(', ')),
|
|
514
|
+
disableMap
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function reportForbiddenDynamicOrder(pathRef, params, errors, disableMap) {
|
|
519
|
+
const resolvedParams = resolveStaticBinding(params, pathRef);
|
|
520
|
+
const dynamicOrderProperty = findDynamicOrderProperty(resolvedParams);
|
|
521
|
+
if (!dynamicOrderProperty) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
reportForbiddenDynamicOrderValue(
|
|
525
|
+
pathRef,
|
|
526
|
+
dynamicOrderProperty.value,
|
|
527
|
+
dynamicOrderProperty,
|
|
528
|
+
errors,
|
|
529
|
+
disableMap
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function isUrlSearchParamsInstance(node, pathRef) {
|
|
534
|
+
const resolved = resolveStaticBinding(node, pathRef);
|
|
535
|
+
return !!(
|
|
536
|
+
resolved &&
|
|
537
|
+
resolved.type === 'NewExpression' &&
|
|
538
|
+
resolved.callee &&
|
|
539
|
+
resolved.callee.type === 'Identifier' &&
|
|
540
|
+
resolved.callee.name === 'URLSearchParams'
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
|
|
407
544
|
function getJsxElementName(nameNode) {
|
|
408
545
|
if (!nameNode) {
|
|
409
546
|
return '';
|
|
@@ -633,6 +770,24 @@ function collectAstLintIssues(sourceCode, errors, warnings, disableMap) {
|
|
|
633
770
|
},
|
|
634
771
|
CallExpression(pathRef) {
|
|
635
772
|
const callee = pathRef.node.callee;
|
|
773
|
+
if (getMemberPropertyName(callee) === 'searchFormDatas') {
|
|
774
|
+
const params = pathRef.node.arguments && pathRef.node.arguments[0];
|
|
775
|
+
reportForbiddenDynamicOrder(pathRef, params, errors, disableMap);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
const urlSearchParamsMethod = getMemberPropertyName(callee);
|
|
779
|
+
if (
|
|
780
|
+
(urlSearchParamsMethod === 'append' || urlSearchParamsMethod === 'set') &&
|
|
781
|
+
callee &&
|
|
782
|
+
callee.type === 'MemberExpression' &&
|
|
783
|
+
isUrlSearchParamsInstance(callee.object, pathRef)
|
|
784
|
+
) {
|
|
785
|
+
const args = pathRef.node.arguments || [];
|
|
786
|
+
if (getStaticStringValue(args[0]) === 'dynamicOrder') {
|
|
787
|
+
reportForbiddenDynamicOrderValue(pathRef, args[1], pathRef.node, errors, disableMap);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
636
791
|
const isSetState = callee &&
|
|
637
792
|
callee.type === 'MemberExpression' &&
|
|
638
793
|
(callee.object.type === 'ThisExpression' ||
|
|
@@ -670,6 +825,13 @@ function collectAstLintIssues(sourceCode, errors, warnings, disableMap) {
|
|
|
670
825
|
pushIssue(warnings, getNodeLine(pathRef.node), 'setState-non-timestamp', t('publish.lint_setstate_non_timestamp'), disableMap);
|
|
671
826
|
}
|
|
672
827
|
},
|
|
828
|
+
NewExpression(pathRef) {
|
|
829
|
+
const callee = pathRef.node.callee;
|
|
830
|
+
if (callee && callee.type === 'Identifier' && callee.name === 'URLSearchParams') {
|
|
831
|
+
const params = pathRef.node.arguments && pathRef.node.arguments[0];
|
|
832
|
+
reportForbiddenDynamicOrder(pathRef, params, errors, disableMap);
|
|
833
|
+
}
|
|
834
|
+
},
|
|
673
835
|
FunctionDeclaration(pathRef) {
|
|
674
836
|
const id = pathRef.node.id;
|
|
675
837
|
if (!id || id.name !== 'renderJsx') {
|
|
@@ -216,7 +216,13 @@ function openyidaCreateRouterBridge(utils) {
|
|
|
216
216
|
if (router && typeof router.push === 'function') {
|
|
217
217
|
bridge.availableMethods.push('push');
|
|
218
218
|
bridge.push = function() {
|
|
219
|
-
|
|
219
|
+
var args = Array.prototype.slice.call(arguments);
|
|
220
|
+
// 完整地址使用 URL 模式,避免平台再次拼接应用路由前缀。
|
|
221
|
+
if (args[3] === undefined && typeof args[0] === 'string' &&
|
|
222
|
+
/^(https?:[/][/]|[/][/]|[/]APP_[^/?#]+([/?#]|$))/i.test(args[0])) {
|
|
223
|
+
args[3] = true;
|
|
224
|
+
}
|
|
225
|
+
return router.push.apply(router, args);
|
|
220
226
|
};
|
|
221
227
|
} else {
|
|
222
228
|
bridge.push = function() {
|
|
@@ -349,8 +355,8 @@ function buildCanvasPageSchemaObject(sourceCode, runtimeCode, importedModules, f
|
|
|
349
355
|
componentName: 'Page',
|
|
350
356
|
id: nextNodeId(),
|
|
351
357
|
props: {
|
|
352
|
-
contentBgColor: 'var(--pod-page-bg-color, var(--color-white, #fff))',
|
|
353
|
-
pageStyle: { backgroundColor: 'var(--pod-page-bg-color, var(--color-white, #fff))' },
|
|
358
|
+
contentBgColor: 'var(--oyd-page-background, var(--pod-page-bg-color, var(--color-white, #fff)))',
|
|
359
|
+
pageStyle: { backgroundColor: 'var(--oyd-page-background, var(--pod-page-bg-color, var(--color-white, #fff)))' },
|
|
354
360
|
contentMargin: '0',
|
|
355
361
|
contentPadding: '0',
|
|
356
362
|
showTitle: false,
|
|
@@ -358,10 +364,17 @@ function buildCanvasPageSchemaObject(sourceCode, runtimeCode, importedModules, f
|
|
|
358
364
|
templateVersion: '1.0.0',
|
|
359
365
|
contentMarginMobile: '0',
|
|
360
366
|
className: 'page_' + nextSuffix(),
|
|
361
|
-
contentBgColorMobile: 'var(--pod-page-bg-color, var(--color-white, #fff))',
|
|
367
|
+
contentBgColorMobile: 'var(--oyd-page-background, var(--pod-page-bg-color, var(--color-white, #fff)))',
|
|
362
368
|
},
|
|
363
369
|
condition: true,
|
|
364
|
-
css:
|
|
370
|
+
css: [
|
|
371
|
+
'.vc-page-yida-page{--yida-form-content-padding:0;--yida-form-content-margin:0;--yida-layout-padding:0}',
|
|
372
|
+
'.vc-deep-container-entry.vc-rootcontent{padding:0!important;margin-top:0!important;margin-right:0!important;margin-bottom:0!important;margin-left:0!important}',
|
|
373
|
+
// 隔离首个子元素的外边距,浮导 margin 不得把整个 Canvas 顶离页面顶部。
|
|
374
|
+
'.yida-code-canvas{display:flow-root}',
|
|
375
|
+
// Canvas 整页的纯容器至少撑满当前视口,避免嵌入时高度塌陷而裁掉内容。
|
|
376
|
+
'.vc-page-yida-pure-container:has(> .yida-code-canvas){min-height:100vh}',
|
|
377
|
+
].join(''),
|
|
365
378
|
methods: {
|
|
366
379
|
__initMethods__: {
|
|
367
380
|
type: 'js',
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { CliError } = require('../core/cli-error');
|
|
4
|
+
const { REQUIRED_BRAND_SCALE_TOKENS, validateThemeCssContent, extractThemeColor } = require('./custom-theme');
|
|
5
|
+
|
|
6
|
+
// Both flat Fast tokens and grouped Plan tokens use one scalar declaration per line.
|
|
7
|
+
function readDesignTokens(markdown) {
|
|
8
|
+
const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(markdown);
|
|
9
|
+
if (!frontmatter) {
|
|
10
|
+
throw new CliError('design.md 缺少包含 token 的 frontmatter', { code: 'DESIGN_THEME_TOKENS_REQUIRED' });
|
|
11
|
+
}
|
|
12
|
+
const tokens = {};
|
|
13
|
+
for (const line of frontmatter[1].split(/\r?\n/)) {
|
|
14
|
+
const match = /^\s*["']?(--[\w-]+)["']?\s*:\s*(.+?)\s*$/.exec(line);
|
|
15
|
+
if (!match) {continue;}
|
|
16
|
+
const name = match[1];
|
|
17
|
+
// YAML comments may follow a quoted value; # inside a color or string is data.
|
|
18
|
+
const scalar = /^("(?:[^"\\]|\\.)*"|'(?:[^']|'')*'|.*?)\s*(?:\s+#.*)?$/.exec(match[2]);
|
|
19
|
+
const raw = scalar[1].trim();
|
|
20
|
+
let value = raw;
|
|
21
|
+
if (raw.startsWith('"')) {
|
|
22
|
+
try { value = JSON.parse(raw); } catch {
|
|
23
|
+
throw new CliError(`token ${name} 必须是单行字符串`, { code: 'DESIGN_THEME_TOKEN_INVALID' });
|
|
24
|
+
}
|
|
25
|
+
} else if (raw.startsWith("'")) {
|
|
26
|
+
if (!raw.endsWith("'")) {throw new CliError(`token ${name} 引号不完整`, { code: 'DESIGN_THEME_TOKEN_INVALID' });}
|
|
27
|
+
value = raw.slice(1, -1).replace(/''/g, "'");
|
|
28
|
+
}
|
|
29
|
+
if (typeof value !== 'string' || !value.trim() || /[;{}\r\n<>]|\/\*|\*\//.test(value) || /^[|>]/.test(value)) {
|
|
30
|
+
throw new CliError(`token ${name} 必须是已确定的单行 CSS 值`, { code: 'DESIGN_THEME_TOKEN_INVALID' });
|
|
31
|
+
}
|
|
32
|
+
if (name in tokens && tokens[name] !== value) {
|
|
33
|
+
throw new CliError(`token ${name} 存在冲突值`, { code: 'DESIGN_THEME_TOKEN_CONFLICT' });
|
|
34
|
+
}
|
|
35
|
+
if (/^--color-brand1-(4|7|8)$/.test(name)) {
|
|
36
|
+
throw new CliError(`平台不支持 ${name}`, { code: 'DESIGN_THEME_TOKEN_INVALID' });
|
|
37
|
+
}
|
|
38
|
+
tokens[name] = value;
|
|
39
|
+
}
|
|
40
|
+
const missing = REQUIRED_BRAND_SCALE_TOKENS.filter(name => !tokens[name]);
|
|
41
|
+
if (missing.length) {
|
|
42
|
+
throw new CliError(`design.md 缺少品牌 token:${missing.join(', ')}`, { code: 'DESIGN_THEME_TOKENS_REQUIRED' });
|
|
43
|
+
}
|
|
44
|
+
return tokens;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function resolveDesignTokens(markdown) {
|
|
48
|
+
const tokens = readDesignTokens(markdown);
|
|
49
|
+
for (const [alias, source] of Object.entries({
|
|
50
|
+
'--color-brand-1': '--color-brand1-10', '--color-brand-2': '--color-brand1-1',
|
|
51
|
+
'--color-brand-3': '--color-brand1-6', '--color-brand-4': '--color-brand1-9',
|
|
52
|
+
})) {
|
|
53
|
+
tokens[alias] = tokens[alias] || tokens[source];
|
|
54
|
+
}
|
|
55
|
+
tokens['--color-group'] = tokens['--color-group'] || [6, 1, 5, 2, 9, 3].map(n => tokens[`--color-brand1-${n}`]).join(', ');
|
|
56
|
+
return tokens;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function applyDesignTokens(template, markdown, previousMarkdown) {
|
|
60
|
+
const tokens = resolveDesignTokens(markdown);
|
|
61
|
+
const previous = previousMarkdown ? resolveDesignTokens(previousMarkdown) : null;
|
|
62
|
+
const changed = Object.fromEntries(Object.entries(tokens).filter(([name, value]) => !previous || previous[name] !== value));
|
|
63
|
+
if (!Object.keys(changed).length) {
|
|
64
|
+
validateThemeCssContent(template);
|
|
65
|
+
extractThemeColor(template);
|
|
66
|
+
return template;
|
|
67
|
+
}
|
|
68
|
+
const root = /^:root\s*\{([\s\S]*?)^\}/m.exec(template);
|
|
69
|
+
if (!root) {throw new Error('应用主题模板缺少 :root');}
|
|
70
|
+
const declarations = /^[ \t]*(--[\w-]+)\s*:\s*([^;]+);/gm;
|
|
71
|
+
const original = Object.fromEntries([...root[1].matchAll(declarations)].map(m => [m[1], m[2].trim()]));
|
|
72
|
+
const brandValues = new Map(REQUIRED_BRAND_SCALE_TOKENS.filter(name => original[name] && changed[name]).map(name => [original[name], tokens[name]]));
|
|
73
|
+
const escaped = [...brandValues.keys()].map(value => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
74
|
+
const brandPattern = new RegExp(escaped.join('|'), 'g');
|
|
75
|
+
const replaceBrand = value => brandValues.size ? value.replace(brandPattern, old => brandValues.get(old)) : value;
|
|
76
|
+
let body = root[1].replace(declarations, (line, name, value) => line.replace(value, () => changed[name] || replaceBrand(value)));
|
|
77
|
+
const extra = Object.entries(changed).filter(([name]) => !(name in original));
|
|
78
|
+
body += extra.map(([name, value]) => ` ${name}: ${value};\n`).join('');
|
|
79
|
+
// Keep scoped nav/light/dark selectors and their variable relationships intact.
|
|
80
|
+
const tail = template.slice(root.index + root[0].length).replace(declarations,
|
|
81
|
+
(line, name, value) => line.replace(value, () => replaceBrand(value)));
|
|
82
|
+
const css = `${template.slice(0, root.index)}:root {${body}}${tail}`;
|
|
83
|
+
validateThemeCssContent(css);
|
|
84
|
+
extractThemeColor(css);
|
|
85
|
+
return css;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { readDesignTokens, applyDesignTokens };
|
package/lib/app/theme-presets.js
CHANGED
|
@@ -126,7 +126,14 @@ function assertPresetThemeKey(themeKey) {
|
|
|
126
126
|
);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
// colour 保存协议只接受平台主题 key;自定义色值另存 themeColor。
|
|
130
|
+
function assertAppThemeKey(themeKey) {
|
|
131
|
+
if (themeKey === 'custom') { return; }
|
|
132
|
+
assertPresetThemeKey(themeKey);
|
|
133
|
+
}
|
|
134
|
+
|
|
129
135
|
module.exports = {
|
|
136
|
+
assertAppThemeKey,
|
|
130
137
|
SUPPORTED_THEME_KEYS,
|
|
131
138
|
APP_THEME_TOKEN_PRESETS,
|
|
132
139
|
APP_THEME_TOKEN_PRESET_KEYS,
|
package/lib/app/update-app.js
CHANGED
|
@@ -16,7 +16,7 @@ const { createAuthRef } = require('../core/yida-client');
|
|
|
16
16
|
const { t } = require('../core/i18n');
|
|
17
17
|
const { buildYidaI18n } = require('../core/yida-i18n');
|
|
18
18
|
const { throwCommandError, throwUsage } = require('../core/command-errors');
|
|
19
|
-
const {
|
|
19
|
+
const { assertAppThemeKey } = require('./theme-presets');
|
|
20
20
|
const {
|
|
21
21
|
buildCustomThemeStyle,
|
|
22
22
|
normalizeCssColorToHex,
|
|
@@ -284,12 +284,19 @@ function buildUpdateAppNamePostData(params, authRef) {
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
function buildUpdateAppPostData(params, currentApp = {}, authRef) {
|
|
287
|
+
assertAppThemeKey(params.colour);
|
|
288
|
+
if (params.colour && params.colour !== 'custom' && (params.themeFile || params.customThemeStyle || params.themeColor)) {
|
|
289
|
+
throw new Error(t('update_app.theme_preset_conflict'));
|
|
290
|
+
}
|
|
287
291
|
const appName = params.name || pickText(currentApp.appName, params.appType);
|
|
288
292
|
const description = params.desc || pickText(currentApp.description, appName);
|
|
289
293
|
const icon = resolveAppIcon(params, currentApp);
|
|
290
294
|
|
|
291
295
|
const currentThemeColor = pickAppField(currentApp, 'themeColor', 'THEME_COLOR');
|
|
292
296
|
const currentCustomThemeStyle = pickAppField(currentApp, 'customThemeStyle', 'CUSTOM_THEME_STYLE');
|
|
297
|
+
if (params.colour === 'custom' && !params.themeColor && !currentThemeColor) {
|
|
298
|
+
throw new Error(t('update_app.custom_theme_color_required'));
|
|
299
|
+
}
|
|
293
300
|
const postDataObj = {
|
|
294
301
|
_csrf_token: authRef.csrfToken,
|
|
295
302
|
_locale_time_zone_offset: '28800000',
|
|
@@ -305,7 +312,7 @@ function buildUpdateAppPostData(params, currentApp = {}, authRef) {
|
|
|
305
312
|
iconUrl: icon,
|
|
306
313
|
colour: params.customThemeStyle || params.themeColor
|
|
307
314
|
? 'custom'
|
|
308
|
-
: (params.colour || currentApp.colour || (currentApp.config && currentApp.config.COLOUR) || 'deepBlue'),
|
|
315
|
+
: (params.colour || currentApp.colour || (currentApp.config && currentApp.config.COLOUR) || (currentThemeColor ? 'custom' : 'deepBlue')),
|
|
309
316
|
// updateApp 的报错文案叫 appMode,但实际接受的请求字段是 mode。
|
|
310
317
|
mode: currentApp.mode || (currentApp.config && currentApp.config.APPMODE) || 'normal',
|
|
311
318
|
type: currentApp.type || (currentApp.config && currentApp.config.APPTYPE) || 'single',
|
|
@@ -339,18 +346,23 @@ function buildUpdateAppPostData(params, currentApp = {}, authRef) {
|
|
|
339
346
|
sentryMode: currentApp.sentryMode || (currentApp.config && currentApp.config.SENTRY_MODE) || 'y',
|
|
340
347
|
};
|
|
341
348
|
|
|
342
|
-
if (params.hideAppNav !== null) {
|
|
349
|
+
if (params.hideAppNav !== null && params.hideAppNav !== undefined) {
|
|
343
350
|
postDataObj.hideAppNav = params.hideAppNav;
|
|
351
|
+
} else {
|
|
352
|
+
const hideAppNav = pickAppField(currentApp, 'hideAppNav', 'HIDE_APP_NAV');
|
|
353
|
+
if (hideAppNav !== undefined && hideAppNav !== null) {
|
|
354
|
+
postDataObj.hideAppNav = hideAppNav;
|
|
355
|
+
}
|
|
344
356
|
}
|
|
345
357
|
if (params.themeColor) {
|
|
346
358
|
postDataObj.themeColor = params.themeColor;
|
|
347
|
-
} else if (params.colour) {
|
|
359
|
+
} else if (params.colour && params.colour !== 'custom') {
|
|
348
360
|
postDataObj.themeColor = '';
|
|
349
361
|
} else if (currentThemeColor !== undefined && currentThemeColor !== null) {
|
|
350
362
|
postDataObj.themeColor = currentThemeColor;
|
|
351
363
|
}
|
|
352
364
|
|
|
353
|
-
if (params.colour && !params.customThemeStyle) {
|
|
365
|
+
if (params.colour && params.colour !== 'custom' && !params.customThemeStyle) {
|
|
354
366
|
// 切回平台预置主题时必须清空旧 CSS,避免 CUSTOM_THEME_STYLE 继续覆盖 colour。
|
|
355
367
|
postDataObj.customThemeStyle = '';
|
|
356
368
|
} else {
|
|
@@ -382,34 +394,89 @@ async function fetchCurrentApp(appType, authRef) {
|
|
|
382
394
|
return response.content || {};
|
|
383
395
|
}
|
|
384
396
|
|
|
397
|
+
function getThemeSettings(app) {
|
|
398
|
+
const rawStyle = pickAppField(app, 'customThemeStyle', 'CUSTOM_THEME_STYLE');
|
|
399
|
+
let customThemeStyle = rawStyle || null;
|
|
400
|
+
if (typeof customThemeStyle === 'string') {
|
|
401
|
+
try { customThemeStyle = JSON.parse(customThemeStyle); } catch { /* Keep malformed data visible to verification. */ }
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
colour: pickAppField(app, 'colour', 'COLOUR') || '',
|
|
405
|
+
themeColor: pickAppField(app, 'themeColor', 'THEME_COLOR') || '',
|
|
406
|
+
customThemeStyle,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function themeSettingsMatch(expected, actual) {
|
|
411
|
+
const normalizeColor = (value) => value ? normalizeCssColorToHex(value) || value : '';
|
|
412
|
+
if (expected.colour !== actual.colour || normalizeColor(expected.themeColor) !== normalizeColor(actual.themeColor)) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
const expectedStyle = expected.customThemeStyle;
|
|
416
|
+
const actualStyle = actual.customThemeStyle;
|
|
417
|
+
if (!expectedStyle || !actualStyle || typeof expectedStyle !== 'object' || typeof actualStyle !== 'object') {
|
|
418
|
+
return expectedStyle === actualStyle;
|
|
419
|
+
}
|
|
420
|
+
return ['enabled', 'iframePropagation'].every((key) => Boolean(expectedStyle[key]) === Boolean(actualStyle[key])) &&
|
|
421
|
+
['cssUrl', 'cssFileName'].every((key) => (expectedStyle[key] || '') === (actualStyle[key] || ''));
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** updateApp 整包保存;与基础设置页一致,读取最新配置后合并,并核验主题资源。 */
|
|
425
|
+
async function saveAppSettings(params, authRef) {
|
|
426
|
+
const currentApp = await fetchCurrentApp(params.appType, authRef);
|
|
427
|
+
const payload = buildUpdateAppPostData(params, currentApp, authRef);
|
|
428
|
+
const response = await requestWithAutoLogin((auth) => httpPost(
|
|
429
|
+
auth.baseUrl,
|
|
430
|
+
`/${params.appType}/query/app/updateApp.json?_api=Form.updateApp&_mock=false&_stamp=${Date.now()}`,
|
|
431
|
+
querystring.stringify({ ...payload, _csrf_token: auth.csrfToken })
|
|
432
|
+
), authRef);
|
|
433
|
+
if (!response || !response.success) { return response; }
|
|
434
|
+
|
|
435
|
+
const expected = getThemeSettings(payload);
|
|
436
|
+
if (!params.colour && !params.themeColor && !params.customThemeStyle && !expected.themeColor && !expected.customThemeStyle) {
|
|
437
|
+
return response;
|
|
438
|
+
}
|
|
439
|
+
let actual;
|
|
440
|
+
let readbackError;
|
|
441
|
+
// 只重试查询,避免重复上传资源或用旧快照再次覆盖设置。
|
|
442
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
443
|
+
if (attempt) { await new Promise((resolve) => setTimeout(resolve, attempt * 250)); }
|
|
444
|
+
try {
|
|
445
|
+
actual = getThemeSettings(await fetchCurrentApp(params.appType, authRef));
|
|
446
|
+
readbackError = undefined;
|
|
447
|
+
if (themeSettingsMatch(expected, actual)) {
|
|
448
|
+
return { ...response, themeVerification: { verified: true, ...actual } };
|
|
449
|
+
}
|
|
450
|
+
} catch (error) {
|
|
451
|
+
readbackError = error.message;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
success: false,
|
|
456
|
+
errorCode: 'APP_THEME_NOT_PERSISTED',
|
|
457
|
+
errorMsg: t('update_app.theme_not_persisted'),
|
|
458
|
+
themeVerification: { verified: false, expected, actual, readbackError },
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
385
462
|
async function applyCustomThemeUpdate(appType, themeParams, authRef) {
|
|
386
463
|
const params = {
|
|
387
464
|
...themeParams,
|
|
388
465
|
appType,
|
|
389
|
-
|
|
390
|
-
logoSource: themeParams.logoSource || 'appIcon',
|
|
391
|
-
layoutDirection: normalizeLayoutDirection(themeParams.layoutDirection || 'side'),
|
|
466
|
+
layoutDirection: normalizeLayoutDirection(themeParams.layoutDirection),
|
|
392
467
|
};
|
|
393
468
|
assertNavTheme(params.navTheme);
|
|
394
469
|
assertLogoSource(params.logoSource);
|
|
395
470
|
|
|
396
471
|
const themeFile = readThemeCssFile(params.themeFile);
|
|
397
472
|
params.themeColor = themeFile.themeColor;
|
|
398
|
-
const currentApp = await fetchCurrentApp(appType, authRef);
|
|
399
473
|
const uploadResponse = await requestWithAutoLogin(
|
|
400
474
|
(auth) => uploadCustomThemeFile(appType, params.themeFile, auth),
|
|
401
475
|
authRef
|
|
402
476
|
);
|
|
403
477
|
params.customThemeStyle = buildCustomThemeStyle(uploadResponse);
|
|
404
478
|
|
|
405
|
-
return
|
|
406
|
-
const requestPath = `/${appType}/query/app/updateApp.json?_api=Form.updateApp&_mock=false&_stamp=${Date.now()}`;
|
|
407
|
-
return httpPost(
|
|
408
|
-
auth.baseUrl,
|
|
409
|
-
requestPath,
|
|
410
|
-
querystring.stringify(buildUpdateAppPostData(params, currentApp, auth))
|
|
411
|
-
);
|
|
412
|
-
}, authRef);
|
|
479
|
+
return saveAppSettings(params, authRef);
|
|
413
480
|
}
|
|
414
481
|
|
|
415
482
|
async function run(args) {
|
|
@@ -444,7 +511,10 @@ async function run(args) {
|
|
|
444
511
|
printUsage();
|
|
445
512
|
throwUsage(t('update_app.missing_update_field'), t('update_app.usage'));
|
|
446
513
|
}
|
|
447
|
-
|
|
514
|
+
assertAppThemeKey(params.colour);
|
|
515
|
+
if (params.colour && params.colour !== 'custom' && (params.themeFile || params.themeColor)) {
|
|
516
|
+
throw new Error(t('update_app.theme_preset_conflict'));
|
|
517
|
+
}
|
|
448
518
|
params.themeColor = normalizeThemeColor(params.themeColor);
|
|
449
519
|
assertNavTheme(params.navTheme);
|
|
450
520
|
assertLogoSource(params.logoSource);
|
|
@@ -482,29 +552,16 @@ async function run(args) {
|
|
|
482
552
|
warn(t('update_app.layout_notice'));
|
|
483
553
|
}
|
|
484
554
|
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
: `/query/app/updateAppName.json?_api=Form.updateAppName&_mock=false&_stamp=${Date.now()}`;
|
|
496
|
-
|
|
497
|
-
const response = await requestWithAutoLogin((auth) => {
|
|
498
|
-
const postDataObj = shellUpdate
|
|
499
|
-
? buildUpdateAppPostData(params, currentApp, auth)
|
|
500
|
-
: buildUpdateAppNamePostData(params, auth);
|
|
501
|
-
const postData = querystring.stringify(postDataObj);
|
|
502
|
-
return httpPost(
|
|
503
|
-
auth.baseUrl,
|
|
504
|
-
requestPath,
|
|
505
|
-
postData
|
|
506
|
-
);
|
|
507
|
-
}, authRef);
|
|
555
|
+
const response = params.themeFile ? await applyCustomThemeUpdate(params.appType, params, authRef)
|
|
556
|
+
: shellUpdate ? await saveAppSettings(params, authRef) : await requestWithAutoLogin((auth) => {
|
|
557
|
+
const postDataObj = buildUpdateAppNamePostData(params, auth);
|
|
558
|
+
const postData = querystring.stringify(postDataObj);
|
|
559
|
+
return httpPost(
|
|
560
|
+
auth.baseUrl,
|
|
561
|
+
`/query/app/updateAppName.json?_api=Form.updateAppName&_mock=false&_stamp=${Date.now()}`,
|
|
562
|
+
postData
|
|
563
|
+
);
|
|
564
|
+
}, authRef);
|
|
508
565
|
|
|
509
566
|
// 输出结果
|
|
510
567
|
if (response && response.success) {
|
|
@@ -515,6 +572,7 @@ async function run(args) {
|
|
|
515
572
|
console.log(JSON.stringify({
|
|
516
573
|
success: true,
|
|
517
574
|
appType: params.appType,
|
|
575
|
+
themeVerification: response.themeVerification,
|
|
518
576
|
updatedFields: {
|
|
519
577
|
name: params.name || undefined,
|
|
520
578
|
desc: params.desc || undefined,
|
|
@@ -531,8 +589,9 @@ async function run(args) {
|
|
|
531
589
|
} else {
|
|
532
590
|
const errorMsg = response ? response.errorMsg || t('common.unknown_error') : t('common.request_failed');
|
|
533
591
|
chalkResult(false, t('update_app.failed', errorMsg));
|
|
534
|
-
console.log(JSON.stringify({ success: false, error: errorMsg
|
|
535
|
-
|
|
592
|
+
console.log(JSON.stringify({ success: false, appType: params.appType, error: errorMsg,
|
|
593
|
+
errorCode: response && response.errorCode, themeVerification: response && response.themeVerification }));
|
|
594
|
+
throwCommandError(errorMsg, { code: response && response.errorCode, details: response && response.themeVerification });
|
|
536
595
|
}
|
|
537
596
|
}
|
|
538
597
|
|
|
@@ -548,4 +607,5 @@ module.exports = {
|
|
|
548
607
|
normalizeLayoutDirection,
|
|
549
608
|
syncSystemIconColor,
|
|
550
609
|
applyCustomThemeUpdate,
|
|
610
|
+
saveAppSettings,
|
|
551
611
|
};
|
|
@@ -141,7 +141,16 @@ const BUILDER_CORE_COMMAND_IDS = Object.freeze([
|
|
|
141
141
|
'get-permission',
|
|
142
142
|
'save-permission',
|
|
143
143
|
'create-app',
|
|
144
|
+
'design-plan.init',
|
|
145
|
+
'design-plan.materialize',
|
|
146
|
+
'design-plan.preview',
|
|
147
|
+
'design-plan.patch',
|
|
148
|
+
'sample',
|
|
149
|
+
'update-app',
|
|
150
|
+
'update-form-config',
|
|
151
|
+
'get-form-config',
|
|
144
152
|
'create-form.create',
|
|
153
|
+
'create-form.batch',
|
|
145
154
|
'create-form.icons',
|
|
146
155
|
'create-page',
|
|
147
156
|
'publish',
|
|
@@ -452,6 +461,11 @@ function buildFullAppArtifactRoute(manifest) {
|
|
|
452
461
|
orchestrator_skill_id: workflow.orchestrator_skill_id,
|
|
453
462
|
requirement_analysis_skill_id: workflow.requirement_analysis_skill_id,
|
|
454
463
|
requirement_brief_path: workflow.requirement_brief_path,
|
|
464
|
+
design_mode_policy: workflow.design_mode_policy,
|
|
465
|
+
navigation_policy: workflow.navigation_policy,
|
|
466
|
+
plan_command_ids: workflow.plan_command_ids,
|
|
467
|
+
theme_command_ids: workflow.theme_command_ids,
|
|
468
|
+
navigation_command_ids: workflow.navigation_command_ids,
|
|
455
469
|
artifact_generation: workflow.artifact_generation,
|
|
456
470
|
};
|
|
457
471
|
}
|