openyida 2026.9.23 → 2026.9.24

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 (96) hide show
  1. package/lib/app/application-entry-urls.js +27 -1
  2. package/lib/app/create-page.js +5 -9
  3. package/lib/app/get-form-config.js +6 -0
  4. package/lib/app/publish.js +20 -1
  5. package/lib/core/agent-capabilities.js +1 -0
  6. package/lib/core/command-manifest.js +31 -3
  7. package/lib/design-plan/entry-navigation.js +10 -1
  8. package/lib/design-plan/materialize.js +6 -4
  9. package/package.json +1 -1
  10. package/yida-skills/skills/yida-app/references/entry-navigation.md +2 -0
  11. package/yida-skills/skills/yida-app/workflow/step-6-main-page.md +1 -1
  12. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +2 -2
  13. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +3 -3
  14. package/yida-skills/skills/yida-create-form-page/SKILL.md +3 -1
  15. package/yida-skills/skills/yida-create-form-page/references/field-definition-guide.md +16 -0
  16. package/yida-skills/skills/yida-create-form-page/references/form-field-properties.md +7 -5
  17. package/yida-skills/skills/yida-create-page/SKILL.md +1 -1
  18. package/yida-skills/skills/yida-design/SKILL.md +3 -1
  19. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +4 -2
  20. package/yida-skills/skills/yida-design/references/native-form-styles.md +58 -0
  21. package/yida-skills/skills/yida-design/references/navigation-decision.md +2 -0
  22. package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +2 -0
  23. package/yida-skills/skills/yida-design/references/theme/theme-token-presets.md +3 -1
  24. package/yida-skills/skills/yida-design/templates/design-themes/README.md +4 -2
  25. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +2 -0
  26. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +2 -0
  27. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +2 -0
  28. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +2 -0
  29. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +3 -1
  30. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +3 -1
  31. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +2 -0
  32. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +2 -0
  33. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +2 -0
  34. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +2 -0
  35. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +3 -1
  36. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +3 -1
  37. package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +2 -0
  38. package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +2 -0
  39. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +3 -1
  40. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +3 -1
  41. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +2 -0
  42. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +2 -0
  43. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +2 -0
  44. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +2 -0
  45. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +2 -0
  46. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +2 -0
  47. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +2 -0
  48. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +2 -0
  49. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +2 -0
  50. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +2 -0
  51. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +2 -0
  52. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +2 -0
  53. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +2 -0
  54. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +2 -0
  55. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +3 -1
  56. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +3 -1
  57. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +2 -0
  58. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +2 -0
  59. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +2 -0
  60. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +2 -0
  61. package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +1 -0
  62. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +3 -1
  63. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/design.md +3 -1
  64. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +2 -0
  65. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md +2 -0
  66. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +3 -1
  67. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/design.md +3 -1
  68. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +2 -0
  69. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +2 -0
  70. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +3 -1
  71. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/design.md +3 -1
  72. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +3 -1
  73. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/design.md +3 -1
  74. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +2 -0
  75. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/design.md +2 -0
  76. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +2 -0
  77. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/design.md +2 -0
  78. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +2 -0
  79. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/design.md +2 -0
  80. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +3 -1
  81. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/design.md +3 -1
  82. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +2 -0
  83. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/design.md +2 -0
  84. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +2 -0
  85. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/design.md +2 -0
  86. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +2 -0
  87. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/design.md +2 -0
  88. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +4 -2
  89. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/design.md +4 -2
  90. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +2 -0
  91. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/design.md +2 -0
  92. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +2 -0
  93. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/design.md +2 -0
  94. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +3 -1
  95. package/yida-skills/skills/yida-page-config/SKILL.md +2 -2
  96. package/yida-skills/skills/yida-publish-page/SKILL.md +8 -1
@@ -28,4 +28,30 @@ function buildApplicationEntryUrls({ appType, baseUrl, systemLink }) {
28
28
  return { appUrl: workbenchUrl, workbenchUrl, adminUrl: `${origin}/${appType}/admin${suffix}` };
29
29
  }
30
30
 
31
- module.exports = { buildApplicationEntryUrls };
31
+ function readRenderNav(config) {
32
+ const value = config && Object.prototype.hasOwnProperty.call(config, 'renderNav')
33
+ ? config.renderNav : config?.isRenderNav;
34
+ if (value === false || value === 'false') {return false;}
35
+ if (value === true || value === 'true') {return true;}
36
+ return null;
37
+ }
38
+
39
+ function buildDisplayPageEntryUrls({ appType, formUuid, baseUrl, config, formType = config?.formType }) {
40
+ if (formType !== 'display' || !/^FORM[-_][A-Za-z0-9_-]+$/.test(formUuid || '')) {return {};}
41
+ if (config?.formType && config.formType !== 'display') {return {};}
42
+ if ((config?.appType && config.appType !== appType) || (config?.formUuid && config.formUuid !== formUuid)) {return {};}
43
+ const appUrls = buildApplicationEntryUrls({ appType, baseUrl });
44
+ if (!appUrls.workbenchUrl) {return {};}
45
+ const origin = new URL(appUrls.workbenchUrl).origin;
46
+ const renderNav = readRenderNav(config);
47
+ const workbenchUrl = `${origin}/${appType}/workbench/${formUuid}`;
48
+ const standaloneUrl = renderNav === false ? `${origin}/${appType}/custom/${formUuid}` : null;
49
+ return {
50
+ url: standaloneUrl || workbenchUrl,
51
+ workbenchUrl,
52
+ standaloneUrl,
53
+ navigationVerification: { renderNav, verified: renderNav !== null },
54
+ };
55
+ }
56
+
57
+ module.exports = { buildApplicationEntryUrls, buildDisplayPageEntryUrls, readRenderNav };
@@ -20,6 +20,7 @@ const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff
20
20
  const { throwCommandError } = require('../core/command-errors');
21
21
  const { buildApiPath } = require('./create-form/api-path');
22
22
  const { fetchFormSchemaInfo } = require('./get-form-config');
23
+ const { readRenderNav, buildDisplayPageEntryUrls } = require('./application-entry-urls');
23
24
 
24
25
  function parseArgs(args) {
25
26
  const openOption = parseOpenOption(args);
@@ -138,14 +139,6 @@ function buildPageInfoPostData(formUuid, pageName, isRenderNav, csrfToken, curre
138
139
  return querystring.stringify(payload);
139
140
  }
140
141
 
141
- function readRenderNav(config) {
142
- const value = config && Object.prototype.hasOwnProperty.call(config, 'renderNav')
143
- ? config.renderNav : config?.isRenderNav;
144
- if (value === false || value === 'false') {return false;}
145
- if (value === true || value === 'true') {return true;}
146
- return null;
147
- }
148
-
149
142
  async function configureNavigationVisibility(authRef, appType, pageId, pageName, isRenderNav) {
150
143
  const verification = { requestedRenderNav: isRenderNav, renderNav: null, verified: false, attempts: 0 };
151
144
  let currentConfig = null;
@@ -268,7 +261,10 @@ async function run(args) {
268
261
  navigationVerification = await configureNavigationVisibility(authRef, appType, pageId, pageName, false);
269
262
  if (navigationVerification.verified) {
270
263
  chalkSuccess(t('create_page.dashboard_config_ok'));
271
- pageUrl = `${authRef.baseUrl}/${appType}/custom/${pageId}?isRenderNav=false`;
264
+ pageUrl = buildDisplayPageEntryUrls({
265
+ appType, formUuid: pageId, baseUrl: authRef.baseUrl,
266
+ config: { formType: 'display', renderNav: navigationVerification.renderNav },
267
+ }).standaloneUrl;
272
268
  } else {
273
269
  dashboardConfigWarning = navigationVerification.error;
274
270
  warn(t('create_page.dashboard_config_failed', dashboardConfigWarning));
@@ -21,6 +21,7 @@ const {
21
21
  const { t } = require('../core/i18n');
22
22
  const { banner, step, label, info, success, error, result } = require('../core/chalk');
23
23
  const { throwCommandError } = require('../core/command-errors');
24
+ const { buildDisplayPageEntryUrls } = require('./application-entry-urls');
24
25
 
25
26
  // 常用配置字段白名单(人读摘要),--json 会输出完整对象
26
27
  const SUMMARY_FIELDS = [
@@ -121,6 +122,9 @@ async function run(args) {
121
122
  }
122
123
 
123
124
  const cfg = resp.content || resp.result || resp.data || {};
125
+ const entryUrls = buildDisplayPageEntryUrls({
126
+ appType: parsed.appType, formUuid: parsed.formUuid, baseUrl: authRef.baseUrl, config: cfg,
127
+ });
124
128
  success(t('get_form_config.read_ok'));
125
129
 
126
130
  if (parsed.json) {
@@ -129,6 +133,7 @@ async function run(args) {
129
133
  appType: parsed.appType,
130
134
  formUuid: parsed.formUuid,
131
135
  config: cfg,
136
+ ...entryUrls,
132
137
  }, null, 2));
133
138
  return;
134
139
  }
@@ -138,6 +143,7 @@ async function run(args) {
138
143
  appType: parsed.appType,
139
144
  formUuid: parsed.formUuid,
140
145
  title: extractTitle(cfg.title),
146
+ ...entryUrls,
141
147
  };
142
148
  SUMMARY_FIELDS.forEach((key) => {
143
149
  if (cfg[key] !== undefined) {
@@ -37,6 +37,8 @@ const { buildPageFile, shouldBuildPageSource } = require('./page-compat');
37
37
  const { warnLargePageSource } = require('./page-size-guard');
38
38
  const { assertPageTemplateCustomized } = require('./page-template-guard');
39
39
  const { fetchFormPageList } = require('./form-navigation');
40
+ const { fetchFormSchemaInfo } = require('./get-form-config');
41
+ const { buildDisplayPageEntryUrls } = require('./application-entry-urls');
40
42
  const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
41
43
  const { assertNoEmojiInValue } = require('../core/no-emoji-guard');
42
44
  const { loadPageSource } = require('./services/page-source-loader');
@@ -834,7 +836,22 @@ async function runMain(argv) {
834
836
 
835
837
  baseUrl = authRef.baseUrl || baseUrl;
836
838
 
837
- const pageUrl = `${baseUrl}/${appType}/workbench/${savedFormUuid}`;
839
+ let pageConfig = null;
840
+ let navigationWarning = null;
841
+ try {
842
+ const configResponse = await fetchFormSchemaInfo(authRef, appType, savedFormUuid);
843
+ if (!configResponse || configResponse.success === false || configResponse.__needLogin || configResponse.__csrfExpired) {
844
+ throw new Error(configResponse?.errorMsg || t('common.request_failed'));
845
+ }
846
+ pageConfig = configResponse.content || configResponse.result || configResponse.data || {};
847
+ } catch (configError) {
848
+ navigationWarning = configError.message || t('common.request_failed');
849
+ }
850
+ const entryUrls = buildDisplayPageEntryUrls({
851
+ appType, formUuid: savedFormUuid, baseUrl: authRef.baseUrl || baseUrl,
852
+ config: pageConfig, formType: 'display',
853
+ });
854
+ const pageUrl = entryUrls.url || `${baseUrl}/${appType}/workbench/${savedFormUuid}`;
838
855
  const publishMode = isCanvas ? 'canvas' : 'native';
839
856
  let healthCheckResult = null;
840
857
  let navOrderResult = null;
@@ -911,6 +928,8 @@ async function runMain(argv) {
911
928
  formUuid: savedFormUuid,
912
929
  version,
913
930
  url: pageUrl,
931
+ ...entryUrls,
932
+ navigationWarning,
914
933
  publishMode,
915
934
  storageMode,
916
935
  bundleId,
@@ -499,6 +499,7 @@ function buildApplicationEntryPolicy(builderPath, env = process.env) {
499
499
  delivery_unit: 'single_application_entry_group',
500
500
  resource_delivery: 'summary_only',
501
501
  internal_artifact_delivery: 'never',
502
+ frontend_delivery: 'Infer standalone for a scoped service frontend, persist page navigation hiding and return the verified publish/get-form-config standaloneUrl. No extra flag or navigation URL parameter. Missing verification is incomplete delivery; never silently omit the frontend or replace it with workbench/admin.',
502
503
  entries: {
503
504
  workbench: 'when_workspace_in_scope',
504
505
  custom: 'when_entry_mode_standalone_and_is_render_nav_false_readback',
@@ -1311,7 +1311,10 @@ const COMMAND_GROUPS = [
1311
1311
  'openyida create-form create APP_XXX "访客登记" .cache/openyida/visitor/fields.json --layout section --theme comfortable --label-align left --icon name-card --locale zh_CN --no-open',
1312
1312
  'openyida commands build create-form.create --app-type APP_XXX --form-title "访客登记" --fields-json-file .cache/openyida/visitor/fields.json --layout section --theme comfortable --label-align left --locale zh_CN --no-open --json',
1313
1313
  ],
1314
- notes: ['Divider accepts the 23 visible platform styles (none is excluded) through field JSON dividerType, not a CLI flag. Omission falls back to bold-with-thin; invalid supplied styles fail. Choose per business page and keep same-level sections consistent; see summary.core_workflows.full_app_build.divider_style_contract.'],
1314
+ notes: [
1315
+ 'Divider accepts the 23 visible platform styles (none is excluded) through field JSON dividerType, not a CLI flag. Omission falls back to bold-with-thin; invalid supplied styles fail. Choose per business page and keep same-level sections consistent; see summary.core_workflows.full_app_build.divider_style_contract.',
1316
+ 'Divider colorType defaults to theme. If default bindings are unsuitable for the current theme, use custom with backgroundColor, secondaryColor and titleColor designed together; explicit user color values are not required. These are field JSON properties, not CLI flags. Dark-content and composite-title guidance is advisory, not a new validation or upload/save gate.',
1317
+ ],
1315
1318
  }),
1316
1319
  command('create-form.icons', ['create-form', 'icons'], 'create-form icons [--json]', 'help.cmd_list_form_icons', {
1317
1320
  requiresLogin: false,
@@ -1437,7 +1440,7 @@ const COMMAND_GROUPS = [
1437
1440
  { name: 'noOpen', type: 'boolean', source: 'option', builder_options: ['--no-open'] },
1438
1441
  { name: 'json', type: 'boolean', source: 'option', builder_options: ['--json'] },
1439
1442
  ],
1440
- notes: ['Canvas publishing runs the same theme and form-open-container structure checks as compile before login or remote writes. --force does not bypass Canvas compilation checks. --health-check verifies saved content; inspect the actual page for runtime behavior. Fixed brand overrides are preserved with structured warnings by default. --strict-theme blocks them; --allow-fixed-brand conflicts with --strict-theme and --fix-theme. --fix-theme requires the migrated controls to be inside a mounted CanvasThemeProvider and compiles before writing. Unproven dynamic render paths require manual migration. No stdin prompts.'],
1443
+ notes: ['Canvas publishing runs the same theme and form-open-container structure checks as compile before login or remote writes. --force does not bypass Canvas compilation checks. --health-check verifies saved content; inspect the actual page for runtime behavior. Fixed brand overrides are preserved with structured warnings by default. --strict-theme blocks them; --allow-fixed-brand conflicts with --strict-theme and --fix-theme. --fix-theme requires the migrated controls to be inside a mounted CanvasThemeProvider and compiles before writing. Unproven dynamic render paths require manual migration. No stdin prompts.', 'Publishing reads persisted page navigation by default without a new flag. With renderNav=false, url and standaloneUrl use the clean /custom/<formUuid> route, with no navigation query parameters; workbenchUrl remains available. Unknown or visible navigation returns standaloneUrl=null; inspect navigationVerification and navigationWarning. A navigation read failure does not undo publication or prove standalone readiness. Configure scoped service frontend pages persistently before publishing; get-form-config can recover the verified URL without republishing.'],
1441
1444
  }),
1442
1445
  command('update-form-config', ['update-form-config'], 'update-form-config <appType> <formUuid> <true|false|keep> "<title>" [--locale zh_CN|en_US|ja_JP]', 'help.cmd_update_form_config', {
1443
1446
  args: [
@@ -1456,7 +1459,7 @@ const COMMAND_GROUPS = [
1456
1459
  { name: 'formUuid', type: 'string', source: 'positional', position: 1, required: true },
1457
1460
  { name: 'json', type: 'boolean', source: 'option', builder_options: ['--json'] },
1458
1461
  ],
1459
- notes: ['Navigation readback uses renderNav first, falling back to isRenderNav only when renderNav is absent. true/false booleans and strings are recognized; missing or invalid values remain unknown. --json includes the raw configuration; the default summary preserves both navigation fields when present.'],
1462
+ notes: ['Navigation readback uses renderNav first, falling back to isRenderNav only when renderNav is absent. true/false booleans and strings are recognized; missing or invalid values remain unknown. --json includes the raw configuration; the default summary preserves both navigation fields when present. For a confirmed display page, both outputs include url, workbenchUrl, standaloneUrl and navigationVerification. Only persisted renderNav=false returns a clean custom standaloneUrl; visible or unknown navigation returns standaloneUrl=null. Route construction does not verify publication or viewer permissions.'],
1460
1463
  }),
1461
1464
  ],
1462
1465
  },
@@ -1829,6 +1832,29 @@ function summarizeLocalizedCommands(commands) {
1829
1832
  fallback: DEFAULT_DIVIDER_TYPE,
1830
1833
  selection: 'Choose by each page business task and visual weight; keep same-level sections consistent within a page. Prefer suitable variation across different business pages. If the scene is unclear or suitable candidates tie, shuffle compatible candidates and rotate across pages, preferring unused styles until exhausted. Record one choice per page in design.md and dividerType before compilation; retries reuse it. Preserve existing supported styles for local edits.',
1831
1834
  invalid_input: 'INVALID_DIVIDER_TYPE diagnostics; create rejects with CREATE_FORM_INVALID_DIVIDER_TYPE. Never silently replace a supplied unsupported style.',
1835
+ color_guidance: {
1836
+ reference: 'yida-skills/skills/yida-design/references/native-form-styles.md#分割线弱背景',
1837
+ mode: 'agent_design_guidance_only',
1838
+ default_mode: 'theme',
1839
+ custom_mode: 'custom',
1840
+ inputs: ['colorType', 'backgroundColor', 'secondaryColor', 'titleColor'],
1841
+ input_location: 'Field JSON for create/batch; changes for update; props in field-props operations for patch. Not CLI flags.',
1842
+ schema_paths: ['Divider.props.colorType', 'Divider.props.backgroundColor', 'Divider.props.secondaryColor', 'Divider.props.titleColor'],
1843
+ default_bindings: {
1844
+ primary: 'var(--color-brand1-6)',
1845
+ secondary: 'var(--color-brand1-2)',
1846
+ text: 'var(--color-text1-4, #171a1d)',
1847
+ },
1848
+ custom_when: 'The user requests colors, or default bindings do not suit the current theme, visual weight or readability. Design all three colors together; do not require user-specified values for each color. Reuse colors across peer sections.',
1849
+ dark_content: 'Distinguish dark content from dark navigation with light content. Treat brand1-2 as a weak brand surface, not permanently near-white. Root secondary overrides may lose to inline component bindings. For local repairs, prefer component colors when global changes would affect other consumers.',
1850
+ composite_titles: 'Consider outer decoration, the actual title surface and the title separately. In inner-ellipse-title the inner ellipse carries the text. Preserve existing supported shapes; do not dim the whole component to fix its background.',
1851
+ solid_title_surfaces: 'For dark-bar and light-left-title/light-center-title/light-house-title/light-hexagon-title, distinguish the primary-colored title block from the secondary strip. Prefer white or near-white on sufficiently dark primary surfaces; if a bright saturated fill weakens white text, deepen the component backgroundColor while preserving its hue. Do not force white onto pale surfaces. Set titleColor explicitly in custom mode instead of retaining its dark default; do not change global body text to fix a local title.',
1852
+ label_coordination: 'Design the divider title, first field label and input as a group. Share font family; use modest title weight/size emphasis, readable neutral labels, coordinated alignment and spacing. Preserve centered decorative headings without centering field labels. Keep the section gap larger than the title-to-first-field gap, and label-to-input spacing compact. Do not dim labels to create hierarchy or repeat excessive saturated decoration. The label role pod-form-label-color is separate from divider titleColor; record choices in existing design.md without new flags or blocking checks.',
1853
+ picker_icons: '--color-fill1-6 is a weak foreground for picker icons; choose a readable auxiliary foreground against the actual input surface, for example the current theme color-text1-3.',
1854
+ lifecycle: 'Record the choice in existing design.md. Revisit custom colors when changing themes; they do not automatically follow theme switching. Do not claim visual verification from a successful command or when preview is unavailable.',
1855
+ new_cli_flags: false,
1856
+ adds_validation_or_blocking: false,
1857
+ },
1832
1858
  },
1833
1859
  page_skill_policy: 'Use YidaCodeCanvas by default for new primary custom pages. Choose yida-custom-page only when the current target has been identified as existing .oyd.jsx/.oyb.jsx/renderJsx/platform Jsx component maintenance; do not switch to yida-custom-page merely because a page needs data, forms, uploads, this.utils.yida.*, or dataSourceMap-like capabilities.',
1834
1860
  form_entry_policy: {
@@ -1904,6 +1930,8 @@ function summarizeLocalizedCommands(commands) {
1904
1930
  custom: {
1905
1931
  include: 'when_entry_mode_standalone_and_is_render_nav_false_readback',
1906
1932
  url: '{base_url}/{appType}/custom/{formUuid}',
1933
+ default_policy: 'A scoped service frontend is a standalone display page even when entryMode was omitted. Plan derives it from role=service and sceneKey; Fast follows the same business intent. Persist page navigation hiding and read it back, without a new flag or navigation URL query. Preserve explicit user choices and backend navigation. Missing verification is incomplete frontend delivery, not permission to silently omit it.',
1934
+ url_source: 'publish.standaloneUrl or post-publish get-form-config.standaloneUrl; require navigationVerification.renderNav=false and verified=true',
1907
1935
  },
1908
1936
  admin: {
1909
1937
  include: 'default_for_complete_application',
@@ -16,6 +16,15 @@ const assert = (condition, message, details) => {
16
16
  };
17
17
 
18
18
  // Resource names are planning references. Runtime IDs and permissions are resolved after creation.
19
+ function resolvePageEntryMode(page, plan, { sceneKey, customNavigation }) {
20
+ const supplied = page.pageSpecHandoff || {};
21
+ const entries = plan.execution?.entryRecommendation?.entries;
22
+ const servicePage = Array.isArray(entries) && entries.some(entry =>
23
+ entry?.role === 'service' && filled(entry.sceneKey) && entry.sceneKey === sceneKey);
24
+ return supplied.entryMode || page.entryMode ||
25
+ (servicePage || customNavigation || supplied.navigation ? 'standalone' : 'platform-shell');
26
+ }
27
+
19
28
  function buildEntryNavigation(plan, resources, pages) {
20
29
  const recommendation = plan.execution?.entryRecommendation;
21
30
  if (recommendation === undefined) {return null;}
@@ -94,4 +103,4 @@ function buildEntryNavigation(plan, resources, pages) {
94
103
  return { recommendation: JSON.parse(JSON.stringify(recommendation)), platformOrder: [...new Set(platformOrder)] };
95
104
  }
96
105
 
97
- module.exports = { buildEntryNavigation, ENTRY_MODES, ENTRY_MODE_SUMMARIES };
106
+ module.exports = { buildEntryNavigation, resolvePageEntryMode, ENTRY_MODES, ENTRY_MODE_SUMMARIES };
@@ -9,7 +9,7 @@ const { normalizePlan, assertThemeProfile } = require('./normalize');
9
9
  const { readJson, writeFiles } = require('./files');
10
10
  const { prepareUpdates } = require('./artifact-updates');
11
11
  const { validateAuthoring } = require('./validate');
12
- const { buildEntryNavigation, ENTRY_MODE_SUMMARIES } = require('./entry-navigation');
12
+ const { buildEntryNavigation, resolvePageEntryMode, ENTRY_MODE_SUMMARIES } = require('./entry-navigation');
13
13
  const { buildPageNavigationPolicy } = require('./navigation-policy');
14
14
  const { buildAssetTasks } = require('../asset/asset-plan');
15
15
  const { mergeParts } = require('./parallel');
@@ -216,7 +216,7 @@ function pageHandoff(page, plan) {
216
216
  detail: 'detail-profile', landing: 'official-homepage', screen: 'data-screen',
217
217
  };
218
218
  const customNavigation = navigationConfig(plan).navigationType === 'custom';
219
- const entryMode = supplied.entryMode || page.entryMode || (customNavigation || supplied.navigation ? 'standalone' : 'platform-shell');
219
+ const entryMode = resolvePageEntryMode(page, plan, { sceneKey: page.sceneKey || scene, customNavigation });
220
220
  requireFact(!customNavigation || entryMode === 'standalone', `自定义导航的页面 ${page.name} 必须使用 standalone 入口`);
221
221
  if (supplied.navigation !== undefined) {
222
222
  const nav = supplied.navigation;
@@ -277,7 +277,9 @@ function pageNavigationRows(page, plan) {
277
277
  const handoff = page.pageSpecHandoff || {};
278
278
  const applicationCustom = navigationConfig(plan).navigationType === 'custom';
279
279
  const menu = handoff.navigation;
280
- const entryMode = handoff.entryMode || page.entryMode || (applicationCustom || menu ? 'standalone' : 'platform-shell');
280
+ const entryMode = resolvePageEntryMode(page, plan, {
281
+ sceneKey: page.sceneKey || sceneForPage(page), customNavigation: applicationCustom,
282
+ });
281
283
  const variants = { top: '顶部', side: '侧边', mixed: '顶部与侧边', dock: '底部' };
282
284
  return [
283
285
  ['访问方式', entryMode === 'standalone' ? '独立页面入口' : '应用工作区入口'],
@@ -613,7 +615,7 @@ function renderProjectApplications(plan, tokens, color, chapter) {
613
615
  '--color-brand1-6': '主色与主要品牌操作', '--color-brand1-1': '品牌悬停',
614
616
  '--color-brand1-9': '品牌按下', '--color-brand1-10': '品牌禁用',
615
617
  '--pod-page-bg-color': '页面画布', '--pod-card-bg-color': '内容容器',
616
- '--color-fill1-5': '独立浮层', '--color-fill1-10': 'Tooltip背景', '--color-text1-5': 'Tooltip前景',
618
+ '--color-fill1-5': '独立浮层', '--color-fill1-6': '弱图标与辅助操作', '--color-fill1-10': 'Tooltip背景', '--color-text1-5': 'Tooltip前景',
617
619
  };
618
620
  return [
619
621
  '## 5. 项目应用与调整规则', '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.9.23",
3
+ "version": "2026.9.24",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "bin/yida.js",
@@ -123,6 +123,8 @@ Fast(直接搭建)与 Plan(先确认方案)使用同一份入口规划
123
123
 
124
124
  ## 规划字段速查(Fast / Plan)
125
125
 
126
+ 前台用途已经确定时,自定义承载页面默认采用独立入口。`role=service` 与页面 `sceneKey` 对应后,Plan 自动推导遗漏的 `entryMode=standalone`,Fast 执行同样规则;不靠页面名称猜测,不新增 CLI 参数。显式的导航要求优先,冲突需核对。取得页面 ID 后持久化隐藏页面导航并回读,发布后交付 `publish` 或 `get-form-config` 返回的 `standaloneUrl`,不追加导航 URL 参数。前台入口属于交付范围时不能因字段漏写或只拿到工作台地址而静默省略;未确认成功须明确列为未完成。
127
+
126
128
  需求文件中的 `entryRecommendation` 在 Plan 初始化后保存在 `execution.entryRecommendation`;Fast 在 PRD 中使用同一结构。旧计划没有此字段时仍可使用;首次完整生成时应明确入口规划。保留已有 `source/reason/taskRefs` 等需求依据。
127
129
 
128
130
  | 字段 | 含义和要求 |
@@ -16,7 +16,7 @@
16
16
  3. 创建页面前核对 PRD/resource context 与 auth snapshot 的 `corpId`。
17
17
  4. `corpId` 不一致 → 先确认重新登录到目标组织,或确认在当前组织继续。
18
18
  5. 创建 display 页面后记录真实主页面 `formUuid`。
19
- 6. PRD 的应用工作区采用自定义导航,或该页已确定 `entryMode=standalone` / 页面隐藏导航时,取得真实 `formUuid` 后立即执行 `openyida update-form-config <appType> <formUuid> false "<页面标题>"` 并 `get-form-config --json` 回读 `renderNav=false`;已有页面按同样规则处理,`create-page --hide-nav` 已配置成功时直接回读即可。该任务与 Step 7 的源码开发并行,不等待代码或发布完成。
19
+ 6. 已确定面向前台用户的自定义页面(如 `entryRecommendation.entries[].role=service`),默认作为独立页面交付,即使遗漏 `entryMode` 也按业务用途补齐为 `standalone`,不要求用户再选择开关。PRD 的应用工作区采用自定义导航,或该页已确定 `entryMode=standalone` / 页面隐藏导航时,取得真实 `formUuid` 后立即执行 `openyida update-form-config <appType> <formUuid> false "<页面标题>"` 并 `get-form-config --json` 回读 `renderNav=false`;已有页面按同样规则处理,配置已正确则不重复写入。该任务与 Step 7 的源码开发并行,不等待代码或发布完成。使用持久化配置,不在自定义页 URL 中追加 `isRenderNav=false`。用户明确要求保留平台导航、普通后台内容页和无关页面局部修改沿用其已有边界。
20
20
  7. 将页面导航配置结果交给 Step 8 做发布后核对。其余自定义页面同样在各自创建/复用成功后配置,不只处理主页面。
21
21
 
22
22
  同一 sceneKey 的前台业务视图共用一个自定义页面;将全部视图交给 Step 7 实现。
@@ -51,8 +51,8 @@ openyida nav-group auto-order <appType>
51
51
  5. 逐入口落实任务顺序与默认页:平台菜单消费 entryRecommendation 派生的 navigationOrder;自定义菜单消费该入口的 menu 和 defaultMenuKey。前台首页不自动进入后台,frontend-only 仍需完成前台菜单排序。
52
52
  6. 从本轮交付的每个业务入口检查实际菜单顺序、默认页面、具体视图和首屏内容。平台排序 `readbackVerified=true` 不证明首页已正确;根入口仍打开错误任务时,继续处理平台支持的默认页配置,能力未验证时交付明确任务链接并标记根入口待验证。平台导航管理页只保留一套跨模块导航,重复时修正页面源码。
53
53
  7. 本步骤配置宜搭平台导航,不要求页面源码实现侧边栏或顶部应用导航;只有 PRD 已规划该入口自己的菜单时才实现,不因平台排序再回头补导航壳。
54
- 7. 本轮任一页面 `entryMode=standalone` 时,Step 6 已在取得页面 ID 后隐藏页面导航;发布和健康检查通过后执行 `openyida get-form-config <appType> <displayPageFormUuid> --json` 核对。配置缺失或变化时才执行 `openyida update-form-config <appType> <displayPageFormUuid> false "<页面标题>"` 并再次回读。只有回读明确为 `renderNav=false` 时,才把干净的 `{base_url}/{appType}/custom/{displayPageFormUuid}` 交给 Step 9 作为独立业务入口;写入或回读失败时只保留工作台入口,不用 `?isRenderNav=false` 猜测成功。
55
- 8. 主页面 `entryMode=platform-shell` 或缺失时,不修改页面导航配置,也不输出独立业务入口。
54
+ 7. 本轮已明确的前台自定义页面默认按 `entryMode=standalone` 处理;不能因 PRD 漏写字段而跳过。Step 6 在取得页面 ID 后隐藏页面导航;发布和健康检查通过后核对 `publish.navigationVerification`,必要时执行 `openyida get-form-config <appType> <displayPageFormUuid> --json`。配置缺失或变化时才执行 `openyida update-form-config <appType> <displayPageFormUuid> false "<页面标题>"` 并再次回读。只有回读明确为 `renderNav=false` 时,才将 CLI 返回的 `standaloneUrl` 交给 Step 9,格式为干净的 `{base_url}/{appType}/custom/{displayPageFormUuid}`;配置失败或结果未知时标记“前台入口未完成”,不能用工作台入口替代交付,也不用 `?isRenderNav=false` 猜测成功。
55
+ 8. 非前台页面明确采用 `entryMode=platform-shell`,或缺少入口用途依据时,不修改页面导航配置。用户已明确保留平台导航的要求优先;用途与规划冲突时先核对,不覆盖明确选择。
56
56
 
57
57
  ## 无自定义页面的管理端
58
58
 
@@ -14,7 +14,7 @@
14
14
  - 页面/资源数量完整性风险检查结果。
15
15
  - `requirement-brief.json.constraints.prohibitedActions` 与对应跳过证据。
16
16
 
17
- 主入口与页面入口必须取自本轮 CLI 成功结果返回的 `appUrl`、`workbenchUrl`、`adminUrl` 或 `url`,并在后续只读回查中保持一致。不得由模型根据 `appType` 自行拼接或猜测链接;下文 URL 规则仅用于校验服务端/CLI 返回值,不是缺失链接时的生成规则。若成功结果没有权威 URL,必须明确交付失败并执行只读回查,不能交付空卡片或用模板补齐。
17
+ 主入口与页面入口必须取自本轮 CLI 成功结果返回的 `appUrl`、`workbenchUrl`、`adminUrl`、`standaloneUrl` 或 `url`,并在后续只读回查中保持一致。前台自定义页面优先使用 `publish` 或发布后 `get-form-config` 回读确认的 `standaloneUrl`;这是页面持久化隐藏导航后的无参数地址。不得由模型根据 `appType` 自行拼接或猜测链接;下文 URL 规则仅用于校验服务端/CLI 返回值,不是缺失链接时的生成规则。若成功结果没有权威 URL,必须明确交付失败并执行只读回查,不能交付空卡片或用模板补齐。
18
18
 
19
19
  入口层级由用户的交付目标决定:应用访问、应用入口或应用工作台使用成功结果的 `appUrl`;具体表单、流程、报表或页面入口使用对应资源结果的 `url` / `workbenchUrl`。同一结果同时提供两种入口时,优先满足用户明确点名的层级。
20
20
 
@@ -57,7 +57,7 @@
57
57
  | 两类入口均在交付范围内,且各自验证通过 | `openyida app-entry set <appType> --frontend <已验证前台完整URL> --management <已验证业务管理完整URL>` |
58
58
  | 两类入口均不适用或尚未验证 | 不执行 `app-entry set`;不传空字符串、`null`、占位 URL,不为了补齐配置创建页面或拼接工作台链接 |
59
59
 
60
- - 前台地址必须来自已发布页面的成功返回及回读;独立前台仍需核验 `isRenderNav=false`。
60
+ - 前台地址必须来自已发布页面的成功返回及回读;独立前台核验持久化 `renderNav=false`,仅字段缺失时兼容 `isRenderNav`,不通过 URL 参数配置。
61
61
  - **登记 URL 必须是发布返回并回读确认的那条完整访问地址,原样传入 `app-entry set`**:直接复用 `publish` 成功返回的完整运行时 URL,并结合 `get-form-config` 核对页面配置和实际访问结果,保留其域名、路径段(如 `/workbench/{formUuid}` 或 `/custom/{formUuid}`)和有效参数。不得手工改写、截断或凭 `appType`/`formUuid` 拼接一条未经发布回读的路径来登记;保存后回读核对同一条完整 URL。完整 URL 参数不会截断工作台页面 ID。
62
62
  - 只有已有明确页面 ID 且无需保留公开地址或参数时,才用 `--frontend-page <formUuid>` / `--management-page <formUuid>`。前者检查 display 类型和非空 pathName,生成 `/custom/<formUuid>`;后者检查页面归属,生成 `/workbench/<formUuid>`。生成路径与配置回读不代替实际访问验收;公开入口始终传已验证的完整 URL。
63
63
  - 已验证的公开地址按完整 URL 原样登记,保留所选入口的域名、路径和有效参数;不能替换成需要登录的长链接,也不能为了登记而自动开启公开访问。
@@ -134,7 +134,7 @@
134
134
  - 新增、修改或发布单个具体页面时,交付当前页面并保持单页范围。
135
135
  - 完整应用的入口组按有效范围交付:不分前后台时提供经验证的“系统入口”,分前后台或只有访问后台时提供经验证的“业务后台入口”:根 `{base_url}/{appType}/workbench` 或上述指定任务/视图链接;明确仅前台时不追加业务后台,但仍提供开发者管理后台。
136
136
  - 只有访问后台时核验业务处理人员的入口、数据范围和操作,不追加前台;只有访问前台且提交后需要处理时,核验已有系统、人员入口或自动流程如何承接,未核验的部分明确说明。
137
- - 前台页面在 PRD 中为 `entryMode=standalone`,且 Step 8 回读确认 `renderNav=false` 时,入口组包含“前台” `{base_url}/{appType}/custom/{formUuid}`;否则不得输出。
137
+ - 业务范围已包含前台自定义页面时,入口组必须包含已验证的“前台”单页面地址。即使 PRD 漏写 `entryMode`,也先补齐独立入口配置,按 Step 8 回读确认 `renderNav=false` 后直接使用 CLI 的 `standaloneUrl`;不得静默省略,不能只返回工作台或开发后台,也不能追加 URL 参数临时隐藏导航。配置或回读未完成时明确列出“前台入口未完成”,不宣称整体交付完成。
138
138
  - 完整应用默认交付“开发者管理后台” `{base_url}/{appType}/admin`,使用 `create-app` 或 `app-list` 成功结果中的 `adminUrl`。`application_entry_policy.entries.admin=include` 不受云端/本地宿主或登录态注入方式影响;不要沿用旧版本云端省略 admin 的规则。地址生成不代表已验证收件人的管理权限,实际访问仍由平台鉴权。
139
139
  - 完整应用一般为 2–3 个地址:有前后台时为“前台、业务后台、开发者管理后台”;仅前台时为“前台、开发者管理后台”;仅业务后台时为“业务后台、开发者管理后台”;不分前后台时为“系统入口、开发者管理后台”。同一业务入口不重复凑数,不为补链接创建额外业务后台。用户明确排除开发者入口时遵从;单页任务保持单页交付范围。
140
140
  - 若历史创建结果缺少 `adminUrl`,分页查询 `app-list` 并匹配真实 `appType`(名称仅辅助识别),保留其 `adminUrl`;不要自行猜租户域名或资源 ID。无法取得时明确标记开发者入口待补齐,不得静默省略或声明交付完成。
@@ -137,6 +137,8 @@ CLI 在同一次 batch 内对已取得真实 `formUuid` 的空壳表单执行一
137
137
  - 组件选用:业务字段负责数据采集,Tab/切换负责导航,按钮组/操作入口执行业务动作,图片或图形建立视觉焦点,状态区提供反馈,标题与 `Divider` 组织层级和节奏,`ColumnContainer` 组织横向字段。编辑已有表单时保留现有组件。
138
138
  - 分组规则:普通业务分组和章节分隔使用 `Divider`;横向字段组合使用 `ColumnContainer`。
139
139
  - Divider 样式:按页面业务、字段密度和主题,从 [23 个可见样式](references/form-field-properties.md#divider) 中选择并显式填写 `dividerType`。同页同层级使用一致样式;编辑已有页面时沿用原样式,不同业务页面按各自设计选择。
140
+ - 深色表单配色:先区分深色内容与仅深色导航,再按[分割线配色引导](../yida-design/references/native-form-styles.md#分割线弱背景)选择背景和标题色。默认继承主题;默认绑定不适合时可用 `colorType: "custom"` 成组设计主色、辅助色、标题色,无需用户逐项指定。内嵌椭圆等复合样式分别考虑外条、内底和文字,不能直接沿用浅底配浅字;已有页面局部修复不随意改动全局品牌色。
141
+ - 主色实底标题与 label:`dark-bar`、`light-left-title` 等样式的文字位于主色块时,优先考虑白色/近白色,并按实际亮度成组调整局部底色;自定义时显式填写 `titleColor`。章节与字段 label 同时考虑字体、字重、对齐和间距,不靠压暗 label 突出章节。具体见[主色实底标题与字段标签](../yida-design/references/native-form-styles.md#主色实底标题与字段标签)。
140
142
 
141
143
  ## 企业级表单质量规则
142
144
 
@@ -157,7 +159,7 @@ CLI 在同一次 batch 内对已取得真实 `formUuid` 的空壳表单执行一
157
159
  - `--theme default|compact|comfortable` 配置页面密度;应用主题 token 配置完整视觉风格。美化已有表单时保留现有 `formUuid` 和字段结构,只更新布局与主题。
158
160
  - 局部多列容器使用统一、克制的背景。
159
161
  - 流程表单优先采用单列和清晰分段,颜色用于章节识别。
160
- - 用户明确指定颜色时,写入 `colorType: "custom"` 和具体色值。
162
+ - 用户指定颜色,或默认绑定不适合当前主题下的分割线时,可写入 `colorType: "custom"`,成组设计主色、辅助色和标题色;无需等待用户逐项指定色值。
161
163
 
162
164
  ## create 模式
163
165
 
@@ -56,6 +56,22 @@
56
56
 
57
57
  按当前页面的业务、密度和主题选择 `dividerType`,同页同层级尽量一致,不同业务页面优先选用不同且合适的样式;无法判断时按页面随机轮换,选定后显式填写,同页复用。完整外观和场景见 [Divider 选型表](form-field-properties.md#divider)。未填写时 CLI 以 `bold-with-thin` 兜底,不替代按场景选型。
58
58
 
59
+ 默认 `colorType: "theme"` 继承主题。默认绑定不适合当前深色内容或复合分割线时,可按[配色引导](../../yida-design/references/native-form-styles.md#分割线弱背景)成组自定义,无需用户逐项指定颜色。例如下面的颜色只用于蓝色深色内容示例,不作为所有应用的固定配方:
60
+
61
+ ```json
62
+ {
63
+ "type": "Divider",
64
+ "title": "基本信息",
65
+ "dividerType": "light-left-bar",
66
+ "colorType": "custom",
67
+ "backgroundColor": "#2AA5FF",
68
+ "secondaryColor": "#1A2D3D",
69
+ "titleColor": "#DEE5EA"
70
+ }
71
+ ```
72
+
73
+ `colorType`、`backgroundColor`、`secondaryColor`、`titleColor` 都是字段 JSON 属性,不是 CLI 参数。create/batch 写在字段对象里;update 写在目标字段的 `changes` 中;patch 写在 `field-props` 操作的 `props` 中,最终保存在 `Divider.props` 的同名属性。同页同层级复用配色;换肤时重新考虑这三个颜色。本引导不新增自动校验或保存/上传阻断。
74
+
59
75
  ### ColumnContainer
60
76
 
61
77
  局部多列使用 ColumnContainer,适合短字段成组:
@@ -52,7 +52,9 @@ Divider > Field
52
52
 
53
53
  - 默认 `Divider` 使用主题模式:不写 `colorType` 或写 `"theme"`。
54
54
  - 不要为了“更好看”给每个 Divider 随机写 `backgroundColor` / `secondaryColor`。
55
- - 只有用户明确指定颜色时,才使用 `colorType: "custom"` 并写 `backgroundColor`、`secondaryColor`、`titleColor`。
55
+ - 主色实底和主色标签上的标题不一定适合正文色。按[标题与 label 搭配](../../yida-design/references/native-form-styles.md#主色实底标题与字段标签)考虑白色/近白色标题与局部深底,自定义配色时显式写 `titleColor`;同页 label 保持清楚的中性文字,用字重、对齐和间距组织层级。
56
+ - 用户指定颜色,或默认主题绑定不适合当前分割线的层次、视觉权重和可读性时,可使用 `colorType: "custom"`,按当前应用主题成组设计 `backgroundColor`、`secondaryColor`、`titleColor`。不要求用户逐项指定色值;同页同层级复用同一配色,并在现有 `design.md` 记录理由,不能逐字段随机配色。
57
+ - 主题模式下,浅底、胶囊、梯形尾部等辅助色消费 `--yida-divider-secondary-color`;组件可能在元素上内联将它指向 `--color-brand1-2`。深色内容先将 `--color-brand1-2` 设计为深色品牌弱背景,再让应用辅助色引用同一变量,不能只修改根级辅助色。生成与实测要求见 [分割线弱背景](../../yida-design/references/native-form-styles.md#分割线弱背景)。
56
58
 
57
59
  ### Divider
58
60
 
@@ -84,9 +86,9 @@ OpenYida 支持以下 **23 个可见样式**,不接受 `none`(无分割线
84
86
  | `double-color-trapezoid` | 主色梯形标题拼浅底横条 | 品牌分区、项目资料 |
85
87
  | `arrow-right-title` | 右箭头标题接浅底横条 | 有明确先后顺序的阶段;样式本身不提供流程操作 |
86
88
  | `square-blocks-title` | 左侧双方块、标题及底部细线 | 项目、资源或技术资料 |
87
- | `inner-ellipse-title` | 主色胶囊横条内嵌浅底椭圆标题 | 轻松的活动、服务专题 |
89
+ | `inner-ellipse-title` | 主色胶囊横条内嵌弱背景椭圆标题,弱背景随内容明暗变化 | 需要强调的少量短标题;按三层配色检查 |
88
90
 
89
- 选型顺序:用户指定的有效样式优先;已有页面局部修改保留原有有效样式;新页面再按下面的业务场景选择。先排除不适合标题长度、内容密度和主题的形态,同页同层级复用一个主样式。
91
+ 选型顺序:用户指定的有效样式优先;已有页面局部修改保留原有有效样式;新页面再按下面的业务场景选择。先排除不适合标题长度、内容密度和主题的形态,同页同层级复用一个主样式。内嵌胶囊及其他多色标题按 [内嵌标题与复合分割线](../../yida-design/references/native-form-styles.md#内嵌标题与复合分割线) 分别检查文字承载面、装饰面积和窄屏;可读性通过不等于适合高频多章节表单。
90
92
 
91
93
  | 页面情况 | 推荐候选 | 选择依据 |
92
94
  | --- | --- | --- |
@@ -97,7 +99,7 @@ OpenYida 支持以下 **23 个可见样式**,不接受 `none`(无分割线
97
99
  | 项目阶段、技术资料、赛事或需要明显章节识别的页面 | `arrow-right-title`、`square-blocks-title`、`multi-parallelograms-end`、`light-hexagon-title`、`hexagon-title` | 用方向或几何形态强化分区;箭头不代表已有流程交互 |
98
100
  | 资质、荣誉、品牌专题或少量重点章节 | `badge-line`、`dark-bar`、`center-title-with-bar`、`thick` | 视觉权重较强,避免在密集页面大量重复 |
99
101
 
100
- **不知道如何选择时,随机轮换。** 场景不明确,或多个候选同样合适时,将合适的候选随机打乱,按页面依次选用。优先用本轮尚未用过的样式,用完再重新打乱;没有可用的场景判断依据时,从全部 23 种中轮换。每页只选一次,同页各分组复用,不逐条随机。
102
+ **不知道如何选择时,随机轮换。** 场景不明确,或多个候选同样合适时,将合适的候选随机打乱,按页面依次选用。优先用本轮尚未用过的样式,用完再重新打乱;没有可用的场景判断依据时,从全部 23 种中先按标题长度、密度、主题可读性与视觉权重筛选,再轮换。每页只选一次,同页各分组复用,不逐条随机。
101
103
 
102
104
  把选定样式和理由(例如“场景不明确,随机轮换”)写入现有 `design.md` 的页面说明,并显式填入该页每个 `Divider.dividerType`。后续生成、编译、重试和局部修改复用已记录的值,不重新抽签,不需要新增状态文件或 CLI 参数。
103
105
 
@@ -120,7 +122,7 @@ OpenYida 支持以下 **23 个可见样式**,不接受 `none`(无分割线
120
122
  | `colorType` | `"theme"` | 配色类型,支持 `"theme"` / `"custom"` |
121
123
  | `backgroundColor` | `"#0089ff"` | 自定义主题色 |
122
124
  | `titleColor` | `"#171a1d"` | 自定义标题色 |
123
- | `secondaryColor` | `"#cce5ff"` | 自定义背景/辅助色 |
125
+ | `secondaryColor` | `"#cce5ff"` | 自定义背景/辅助色;仅在 `colorType: "custom"` 时使用,主题模式按上述规则成组设计 `--color-brand1-2` 与 `--yida-divider-secondary-color` |
124
126
 
125
127
  ### ColumnContainer
126
128
 
@@ -58,7 +58,7 @@ openyida create-page <appType> "<pageName>" [--mode dashboard] [--hide-nav] [--l
58
58
  | `appType` | 是 | 应用 ID,如 `APP_XXX` |
59
59
  | `pageName` | 是 | 页面名称 |
60
60
  | `--mode dashboard` | 否 | 看板/驾驶舱页面推荐使用;只表达页面模式,不会自动隐藏导航 |
61
- | `--hide-nav` | 否 | 仅当用户显式要求页面隐藏导航 / 无导航 / 全屏无框时使用;命令自动配置并回读,未生效时在同一页面补写一次。确认隐藏后才输出 `hideNav=true` 和带 `isRenderNav=false` 的 URL;这不等同于应用导航隐藏,自绘应用侧导航需另执行 `openyida update-app <appType> --hide-app-nav` |
61
+ | `--hide-nav` | 否 | 兼容已有的显式隐藏导航调用;命令自动配置并回读,未生效时在同一页面补写一次。确认隐藏后才输出 `hideNav=true` 和不带导航参数的 `/custom/<pageId>`。完整应用的前台用途由编排判断,创建后通过持久化页面配置完成,不要求用户传此开关;这不等同于应用导航隐藏 |
62
62
  | `--locale` | 否 | 页面内容语言:`zh_CN`、`en_US`、`ja_JP`;省略时按当前环境选择 |
63
63
  | `--open` / `--no-open` | 否 | 控制成功后是否返回浏览器打开提示,由宿主执行打开,不影响页面配置 |
64
64
 
@@ -45,7 +45,9 @@ Fast、Plan 和单页设计使用相同的 UI 设计规则、主题变量和质
45
45
 
46
46
  ---
47
47
 
48
- 用户选择暗色、黑色或夜间主题时,按 [暗色主题浮层适配](references/theme/theme-token-presets.md#暗色主题浮层适配) 检查浮层;仅导航深色不触发整体暗黑适配。
48
+ 用户选择暗色、黑色或夜间主题时,按 [暗色主题浮层适配](references/theme/theme-token-presets.md#暗色主题浮层适配) 检查浮层,并按 [分割线弱背景](references/native-form-styles.md#分割线弱背景) 设计 `--color-brand1-2` 与标题文字:它是随内容明暗变化的品牌弱背景,不是固定近白色。不能只声明根级 `--yida-divider-secondary-color` 就认为组件内联引用已被覆盖。仅导航深色不触发整体暗黑适配。
49
+
50
+ 主色实底分割线不沿用弱背景的文字配法:根据[主色实底标题与字段标签](references/native-form-styles.md#主色实底标题与字段标签),优先考虑白色/近白色标题与适合的局部品牌底,并与字段 label 的字体、字重、对齐和间距成组设计。不要机械地全页白字,也不要为突出章节把 label 弱化到难读。
49
51
 
50
52
  ## Fast 视觉流程
51
53
 
@@ -93,6 +93,8 @@ JSON `paletteContrast.checks` 表示可计算的组合;`unresolved` 列出不
93
93
  - **值的类型**:颜色、渐变/图片、长度、字体、阴影、时间和缓动分别用于匹配的 CSS 属性。共享渐变可以存入主题变量,由页面的 `background-image` 消费;用于 `background-color` 的平台变量仍保持颜色值。
94
94
  - **范围与复用**:稳定的主题值和复用组件参数进入主题;一次性的布局尺寸、局部状态和装饰可留在页面。避免为同一角色重复命名,也不要求把每个 CSS 常量都变成 token。
95
95
 
96
+ 平台基础色阶中的 `--color-fill1-6` 被原生图标、弱操作和选择器末尾按钮消费,应声明为可读的弱前景色。暗色或黑色内容界面优先让它跟随 `--color-text1-3` 这类当前主题的辅助文字色,不依赖组件样式中的固定 fallback。
97
+
96
98
  `application-global` 与 `custom-page` 是设计文档的组织分组,不是 CSS 隔离作用域。两组声明都会写入应用主题的 `:root`,扩展变量可跨页使用,也可被平台变量引用;引用必须已声明且无循环。仅在某个页面选择器内定义的局部变量不能充当全应用依赖。保留现有分组即可,不另加一套文件或交接字段。
97
99
 
98
100
  ## 先把风格落到变量
@@ -151,11 +153,11 @@ JSON `paletteContrast.checks` 表示可计算的组合;`unresolved` 列出不
151
153
 
152
154
  分割线按页面用途选择,不跟随主题模板固定成一种。高频录入重扫描效率,可用圆点、简线或浅底;资料审核重分组识别,可用带条浅底;活动、品牌专题才考虑居中标签或几何装饰。这些是候选方向,不是行业到样式的一一映射。
153
155
 
154
- 同页同层级的分组标题尽量保持线型、装饰、对齐和配色一致;不同业务页面优先选择不同且合适的类型。先比较用途、密度、标题长度和主题,再决定差异;相同任务可以复用;场景不明确或候选同样合适时,将候选随机打乱后按页面轮换,优先用本轮未使用的样式,用完再重排。没有场景判断依据时,从全部 23 种中轮换;每页只选一次,同页复用,后续修改和重试不重新抽签。普通表格网格、卡片边框和章节分割线分别处理,不为了差异把整页边框都换成装饰线。
156
+ 同页同层级的分组标题尽量保持线型、装饰、对齐和配色一致;不同业务页面优先选择不同且合适的类型。先比较用途、密度、标题长度和主题,再决定差异;相同任务可以复用;场景不明确或候选同样合适时,将候选随机打乱后按页面轮换,优先用本轮未使用的样式,用完再重排。没有场景判断依据时,从全部 23 种中先按标题长度、密度、主题可读性与视觉权重筛选,再轮换;每页只选一次,同页复用,后续修改和重试不重新抽签。普通表格网格、卡片边框和章节分割线分别处理,不为了差异把整页边框都换成装饰线。
155
157
 
156
158
  在现有 `design.md` 的页面说明中写“页面、分割线样式、选择理由”,无需增加文档或必填机器字段。原生表单从 `yida-create-form-page/references/form-field-properties.md#divider` 的 23 个可见样式中选型,排除 `none`,通过 `Divider.dividerType` 配置;Canvas 按相同原则实现分组标题,不假定可直接使用平台 Divider 组件。Fast 与 Plan 均按页面选择。
157
159
 
158
- 同一应用保持字体、间距和整体配色协调,差异主要来自分组形态与视觉轻重。平台主题模式使用品牌主色、浅色和正文色;`dark-bar` 表示实底标题条,并非固定黑色。强色底需检查文字可读性,长标题和窄屏优先使用简单形态。已有页面的局部修改保持原样式,只有本次明确调整分组设计时才更换。
160
+ 同一应用保持字体、间距和整体配色协调,差异主要来自分组形态与视觉轻重。平台主题模式使用品牌主色、随内容明暗变化的品牌弱背景和正文色;`dark-bar` 表示实底标题条,并非固定黑色。强色底需检查文字可读性,长标题和窄屏优先使用简单形态。内嵌椭圆、双色标签等分别检查外条、标题承载面与文字,见 [复合分割线](native-form-styles.md#内嵌标题与复合分割线);不要因为整条的对比度通过就忽略内层浅字浅底或装饰抢占视觉的问题。已有页面的局部修改保持原样式,只有本次明确调整分组设计时才更换。
159
161
 
160
162
  ## 页面只引用设计值
161
163
 
@@ -40,10 +40,67 @@
40
40
  | `--input-border-width` | 输入边框宽度 | `1px` |
41
41
  | `--input-border-color` | 输入边框颜色 | `rgba(24, 28, 31, .12)` |
42
42
  | `--pod-form-label-color` | 字段标签 `color` | `var(--color-text1-10, rgba(24, 28, 31, .8))` |
43
+ | `--color-fill1-6` | 成员选择器末尾按钮等弱图标的前景色 | `#878f95`;深色下按实际输入背景选择可读的辅助前景色 |
43
44
  | `--form-top-label-margin-b` | 顶部标签 `margin-bottom` | `0` |
45
+ | `--yida-divider-secondary-color` | Divider 浅底、胶囊和辅助几何色 | `var(--color-brand1-2)` |
44
46
 
45
47
  表中的回退不是必须写死的设计值。模板将圆角连接到 `--corner-2`,填充连接到 `--pod-card-bg-color`,边框连接到 `--color-line1-2`,标签连接到 `--color-text1-10`;项目可以按语义单独调整。高度和使用同一变量的行高一起变化,不再增加一个平行行高变量。
46
48
 
49
+ ### 分割线弱背景
50
+
51
+ `--color-brand1-2` 表示品牌弱背景,不代表任何主题下都接近白色。根据 `themeProfile.contentTone` 与实际内容底色选择:浅色内容可与白色混合;暗黑/深色内容应与深色画布混合。设计深色方案时,可从主色 12% + `--pod-page-bg-color` 88% 的 sRGB 混合开始,最终按标题可读性与项目风格调整;这不是固定配方,也不能因 `navTheme: dark` 就把浅色内容的品牌弱背景改暗。
52
+
53
+ 主题模式下的原生 Divider 在已验证的平台版本中会内联声明 `--yida-divider-secondary-color: var(--color-brand1-2)`;`inner-ellipse-title` 的内椭圆还会直接内联 `background-color: var(--color-brand1-2)`。继续使用主题模式时,应先在设计源里修正 `--color-brand1-2`,并令应用级 `--yida-divider-secondary-color` 同样引用它;只在 `:root` 把辅助色改为边界色无法覆盖这些声明。这些是默认绑定,不是配色限制;复合样式可按下节使用组件自定义配色。不要用全局 `!important`、逐字段随机配色或改成简单线型掩盖问题。
54
+
55
+ 以上是 Agent 的配色引导,不新增 CLI 参数、自动检查或保存/上传阻断。不要将模板生成或已有命令成功当作分割线可读的证明。预览时关注实际提交页、抽屉和详情里的 `light-left-bar`、`light-bar`、`inner-ellipse-title`:以标题所在子节点的背景为准,而不只看根节点 token。普通标题可按 4.5:1 作为可读性参考;成员选择器等必要图标可按与输入背景 3:1 作为参考。无法预览时说明尚未实测,不宣称已适配。
56
+
57
+ 新建应用时统筹主题色;已有应用只修复少数分割线时,若调整 `--color-brand1-2` 会影响其他消费者,优先按下节配置局部自定义配色。不要为修复一个标题连带更改全局按钮、链接或选中态。
58
+
59
+ ### 内嵌标题与复合分割线
60
+
61
+ `inner-ellipse-title` 不是单一背景:外层主色横条、内层弱背景胶囊和标题文字分别承担强调、承载和阅读作用。深色方案不能简单套“品牌色横条+白色胶囊+浅字”,也不能将整条透明度调低而连带削弱标题。
62
+
63
+ | 层次 | 已验证的主题模式消费 | 检查要点 |
64
+ | --- | --- | --- |
65
+ | 外层横条 | `--yida-divider-primary-color` → `--color-brand1-6` | 与内容面协调;观察整页反复出现时的视觉权重,不因装饰面积大就全局调暗按钮和链接共用的主色 |
66
+ | 内椭圆 | 直接引用 `--color-brand1-2` | 深色内容使用深色弱背景,与外条保留可辨层次;不能仅检查父节点的辅助色 |
67
+ | 标题 | `--color-text1-4`,透过透明文字容器显示内椭圆背景 | 对比度按文字与实际内椭圆底色计算,至少 4.5:1,不按文字与外层主色或页面底色计算 |
68
+
69
+ 双色梯形、徽章、屋顶、六边形等也按实际标题承载区域逐层检查,不能把内椭圆的配色关系机械套给主色实底标题。装饰边界不承担操作状态时,不把它误当按钮边框强制要求 3:1;但标题、必要图标及真正可操作控件仍遵循各自对比度要求。
70
+
71
+ 默认绑定不适合该分割线时,可以配置 `colorType: "custom"`,分别用 `backgroundColor`、`secondaryColor`、`titleColor` 控制主色、辅助色和标题。根据当前主题成组设计,例如单独减弱外条的亮度和饱和度、使用深色内椭圆与可读浅字,不必连带修改按钮和链接共用的应用主色。无需用户逐项指定颜色;同页同层级复用该配色,并记录到现有 `design.md`。自定义配色不会自动跟随应用换肤;修改主题时需同步复核组件配置,不能假设应用 token 校验已经验证了字段里的颜色。
72
+
73
+ ### 主色实底标题与字段标签
74
+
75
+ 先识别文字真正落在哪个色块,再选择前景色,不从 `light-*` / `dark-*` 的样式名推断文字颜色:
76
+
77
+ | 标题承载面 | 样式示例 | 配色方向 |
78
+ | --- | --- | --- |
79
+ | 主色实底或主色标签 | `dark-bar`、`light-left-title`、`light-center-title`、`light-house-title`、`light-hexagon-title` | 深色或较强的品牌底上,优先考虑白色或近白色标题,不机械继承深色正文色 |
80
+ | 弱背景条 | `light-left-bar`、`light-bar` | 按该弱背景的实际明暗配标题色,不因页面是暗黑就一律用白字 |
81
+ | 内椭圆 | `inner-ellipse-title` | 标题匹配内椭圆的辅助色,不能照搬外条的主色配法 |
82
+
83
+ 饱和度高不等于底色足够暗。优先白字仍需考虑实际亮度;若白字在亮紫等主色上显得发虚,可以单独加深该组件的 `backgroundColor`,保留品牌色相和协调的 `secondaryColor`。浅黄、浅青等浅底不机械使用白字。选择自定义配色时显式填写 `titleColor`,避免只改主色/辅助色后遗漏标题,继续使用默认的 `#171a1d`。不要为一个色块标题把全局 `--color-text1-4` 或所有 label 改成白色。
84
+
85
+ 例如深紫色实底章节可以从以下配色开始;它只是局部设计示例,不是统一 preset,也不代表截图中应用已经修复:
86
+
87
+ ```json
88
+ { "type": "Divider", "title": "交易信息", "dividerType": "dark-bar", "colorType": "custom", "backgroundColor": "#6D28D9", "secondaryColor": "#2D2244", "titleColor": "#FFFFFF" }
89
+ ```
90
+
91
+ 分割线是章节标题,表单 label 是字段标题,应放在一起设计,而不是各自挑选颜色:
92
+
93
+ - 使用同一字体家族;章节标题可比 label 稍大或稍重,例如常规密度下从 16px/600 与 14px/400–500 开始,再按已有主题调整,不用夸张字号争夺注意力。
94
+ - 深色表单的品牌底标题可以用白色/近白色;label 保持足够清楚的中性浅色。层级主要由底色、字重和间距建立,不靠把 label 压暗到难以阅读。label 的主题角色仍是 `--pod-form-label-color`,不与分割线 `titleColor` 混为一个设置。
95
+ - 左对齐章节的文字起点与下面字段组协调;居中或几何标题可以保留,但不带动字段 label 居中。章节上方留白一般大于标题到首行字段的距离,label 到输入框保持更紧凑,让字段自然归属于章节。
96
+ - 章节已有色块时避免再叠加同样强的标签底色、粗边框和大面积高饱和色。重复多组时观察整张表单的节奏,减少装饰抢占输入内容的注意力。
97
+
98
+ 预览时以“章节标题+首行 label+输入框”为一个组合看效果,兼顾同页其他章节、长标题和抽屉宽度。在现有 `design.md` 记录配色与层级选择即可,不增加 CLI 参数、固定布局或自动阻断。
99
+
100
+ 选型时把“可读”与“适合页面”分开判断:高频录入、多分组或长标题的新页面优先比较简单线型和弱底条;内嵌胶囊等强装饰适合有明确强调需求的少量短标题。用户指定或已有样式先保留并修正配色,测试矩阵也保留该样式,不用换形态冒充适配成功。优先用已有组件配色属性表达,不臆造 token 或改全局主色掩盖局部问题。
101
+
102
+ 在提交、详情及实际窄容器分别检查最长标题、内外留白、截断和溢出;纯章节标题不额外添加 hover、指针或点击行为,避免胶囊被误认成按钮。将配色、适用理由和未解决的布局限制记录在现有 `design.md`,随机轮换只在满足这些条件的候选中进行。
103
+
47
104
  以下是不同方向的起点,按主题和真实业务选择,不随机逐字段切换,也不作为 CLI preset:
48
105
 
49
106
  | 方向 | 控件圆角 / 高度 / 字号 | 填充与边框 | 顶部标签间距 |
@@ -138,6 +195,7 @@ Fast 将以下变量合并到 `design.md` 的 `tokens.application-global`;Plan
138
195
  "--input-border-width": "1px",
139
196
  "--input-border-color": "#D8CDBD",
140
197
  "--pod-form-label-color": "#554B40",
198
+ "--yida-divider-secondary-color": "var(--color-brand1-2)",
141
199
  "--form-top-label-margin-b": "6px",
142
200
  "--pod-field-preview-bg-color": "#F7F1E7",
143
201
  "--pod-field-preview-border-radius": "6px",