openyida 2026.10.21 → 2026.10.22

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 (53) hide show
  1. package/README.md +4 -2
  2. package/lib/app/canvas-compile.js +8 -0
  3. package/lib/app/page-linter.js +10 -0
  4. package/lib/app/responsive-layout-guard.js +82 -0
  5. package/lib/core/command-manifest.js +15 -7
  6. package/lib/core/locales/en.js +50 -2
  7. package/lib/core/locales/zh.js +50 -2
  8. package/lib/core/query-data.js +40 -2
  9. package/lib/core/sample.js +3 -0
  10. package/lib/feedback/feedback.js +2 -1
  11. package/lib/feedback/github-setup.js +97 -0
  12. package/lib/feedback/github.js +17 -8
  13. package/lib/feedback/report.js +35 -15
  14. package/lib/integration/integration-triggers.js +8 -3
  15. package/lib/process/configure-process.js +8 -2
  16. package/lib/process/process-tasks.js +175 -0
  17. package/lib/process/services/process-actor-config.js +3 -0
  18. package/lib/process/services/process-compiler.js +15 -0
  19. package/lib/process/services/process-dynamic-actors.js +165 -0
  20. package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +1 -1
  21. package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +1 -1
  22. package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +1 -1
  23. package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +36 -24
  24. package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +1 -1
  25. package/lib/samples/openyida-scaffold/canvas-responsive-layout.jsx +104 -0
  26. package/package.json +1 -1
  27. package/scripts/postinstall.js +1 -0
  28. package/yida-skills/SKILL.md +3 -2
  29. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +5 -1
  30. package/yida-skills/skills/yida-custom-page/SKILL.md +6 -2
  31. package/yida-skills/skills/yida-data-management/SKILL.md +24 -3
  32. package/yida-skills/skills/yida-data-management/references/process-task-transfer.md +53 -0
  33. package/yida-skills/skills/yida-density/SKILL.md +6 -1
  34. package/yida-skills/skills/yida-design/SKILL.md +1 -1
  35. package/yida-skills/skills/yida-design/references/responsive-layout.md +69 -22
  36. package/yida-skills/skills/yida-design/references/task-driven-visual-design.md +2 -0
  37. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +1 -0
  38. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +1 -1
  39. package/yida-skills/skills/yida-design/workflow/output-design.md +2 -2
  40. package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +2 -0
  41. package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +10 -10
  42. package/yida-skills/skills/yida-feedback/SKILL.md +22 -5
  43. package/yida-skills/skills/yida-feedback/references/github-contribution.md +14 -8
  44. package/yida-skills/skills/yida-feedback/references/github-setup.md +74 -0
  45. package/yida-skills/skills/yida-feedback/references/report-input.md +10 -2
  46. package/yida-skills/skills/yida-feedback/references/user-interaction.md +19 -2
  47. package/yida-skills/skills/yida-flow-node-config/SKILL.md +1 -1
  48. package/yida-skills/skills/yida-flow-node-config/references/actors.md +4 -0
  49. package/yida-skills/skills/yida-flow-node-config/references/dynamic-actors.md +84 -0
  50. package/yida-skills/skills/yida-integration/SKILL.md +1 -0
  51. package/yida-skills/skills/yida-integration/references/triggers.md +14 -1
  52. package/yida-skills/skills/yida-prd/SKILL.md +1 -0
  53. package/yida-skills/skills-index.json +13 -4
package/README.md CHANGED
@@ -446,7 +446,9 @@ openyida feedback report --input summary.json --output-dir feedback-draft-001
446
446
 
447
447
  Your AI prepares the summary from observed evidence and selected reproduction screenshots. PRs include before/after test comparisons. Before anything is published, review the final text and images, confirm sensitive information, and remove anything you do not want to share. See the [report input format](yida-skills/skills/yida-feedback/references/report-input.md). Review business information before sharing. With a GitHub account, authorize your AI to submit an Issue or contribute a verified public OpenYida fix through your personal Fork. Without an account, create a GitHub account first. If that is not possible, share the report in the AI开发者群 (AI developer group).
448
448
 
449
- When you choose to submit an OpenYida Issue, the feedback Skill can check your signed-in GitHub account with `openyida feedback github status --json`. Star and a personal Fork are optional: `feedback github star --confirm` and `feedback github fork --confirm` run only after you choose them. Existing actions are reused. This check is separate from installation and automatic updates; neither action is required to submit an Issue.
449
+ To configure a submission tool, your AI can first run `openyida feedback github setup --json` to check gh and the current account. After you approve the installation plan, it can run `openyida feedback github setup --install --confirm --json`, using existing Homebrew on macOS/Linux or WinGet on Windows. Without a supported manager, official instructions or the web remain available. Browser authorization is a separate step performed by you; installation does not log you in, request passwords or tokens, or replace public-content approval. Resume the original draft after setup. See the [account and tool guide](yida-skills/skills/yida-feedback/references/github-setup.md).
450
+
451
+ When preparing a PR that needs a personal Fork, or when you ask how to support the project, the feedback Skill can inspect account support state with `openyida feedback github status --json`. Star and a personal Fork are optional: `feedback github star --confirm` and `feedback github fork --confirm` run only after you choose them. Existing actions are reused. This check is separate from installation and automatic updates; neither action is required to submit an Issue.
450
452
 
451
453
  <!-- OPENYIDA_COMMANDS_START -->
452
454
  <!-- This section is generated by `npm run docs:commands`. Do not edit command rows by hand. -->
@@ -530,7 +532,7 @@ When you choose to submit an OpenYida Issue, the feedback Skill can check your s
530
532
 
531
533
  | Command | Description |
532
534
  |---------|-------------|
533
- | `openyida data <query\|get\|create\|update> <resource> ... \| delete form <appType> <formUuid> --inst-id <id> --expect-form-name <name> --expect-form-type receipt --confirm [--json]` | Unified data management (form/process/task/subform) |
535
+ | `openyida data <query\|get\|create\|update\|transfer> <resource> ... \| delete form <appType> <formUuid> --inst-id <id> --expect-form-name <name> --expect-form-type receipt --confirm [--json]` | Unified data management (form/process/task/subform) |
534
536
  | `openyida task-center <todo\|created\|done\|cc\|proxy\|capabilities\|scaffold\|options\|inspect\|count> [--spec <file.json> --output <file.canvas.jsx>] [options]` | Global task center (todo/processed/cc etc.) |
535
537
  | `openyida basic-info <overview\|commodity\|grant\|capacity\|quota\|abs-path\|dataflow\|i18n\|domain>` | Query organization basic info, capacity, quotas, and domain settings |
536
538
  | `openyida read-dingtalk-doc <docUrl> [--output <file>] [--json]` | Fetch Markdown content from a DingTalk document |
@@ -55,6 +55,7 @@ const { assertCanvasThemeStructure } = require('./canvas-theme-guard');
55
55
  const { assertCanvasIconExports } = require('./canvas-icon-guard');
56
56
  const { assertCanvasNavigationStructure } = require('./canvas-navigation-guard');
57
57
  const { assertCanvasNavigationPaths } = require('./canvas-path-guard');
58
+ const { findResponsiveLayoutIssues } = require('./responsive-layout-guard');
58
59
 
59
60
  /**
60
61
  * 依赖 → window 别名白名单,用于把 import 改写到运行时全局对象。
@@ -977,6 +978,13 @@ function compileCanvasLocal(source, options = {}) {
977
978
  assertCanvasNavigationPaths(source, options);
978
979
  assertInlineCssStructure(source, options);
979
980
  const warnings = [];
981
+ findResponsiveLayoutIssues(source).forEach((issue) => {
982
+ warnings.push({
983
+ line: issue.line,
984
+ rule: issue.rule,
985
+ message: t(issue.messageKey, ...(issue.params || [])),
986
+ });
987
+ });
980
988
  assertCanvasThemeStructure(source, { ...options, onThemeWarning(message, details) {
981
989
  warnings.push({ ...details, message });
982
990
  if (options.onThemeWarning) { options.onThemeWarning(message, details); }
@@ -9,6 +9,7 @@ const {
9
9
  const { findBareCjkJsxTextIdentifiers } = require('./jsx-text-guard');
10
10
  const { findDirectFormOpenIssues } = require('./form-open-guard');
11
11
  const { findFormDetailLinkIssues } = require('./form-detail-link-guard');
12
+ const { findResponsiveLayoutIssues } = require('./responsive-layout-guard');
12
13
  const Babel = require('@babel/standalone');
13
14
 
14
15
  const THEN_CALLBACK_LINE_LIMIT = 50;
@@ -1051,6 +1052,15 @@ function lintYidaSource(sourceCode, filePath) {
1051
1052
  findFormDetailLinkIssues(sourceCode, { parserOptions: PARSER_OPTIONS }).forEach((issue) => {
1052
1053
  pushIssue(errors, issue.line, 'form-detail-link', t('publish.lint_form_detail_link'), disableMap);
1053
1054
  });
1055
+ findResponsiveLayoutIssues(sourceCode).forEach((issue) => {
1056
+ pushIssue(
1057
+ warnings,
1058
+ issue.line,
1059
+ issue.rule,
1060
+ t(issue.messageKey, ...(issue.params || [])),
1061
+ disableMap
1062
+ );
1063
+ });
1054
1064
  return { errors, warnings };
1055
1065
  }
1056
1066
 
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ const FIXED_WIDTH_THRESHOLD = 480;
4
+
5
+ function getLine(source, index) {
6
+ return source.slice(0, index).split('\n').length;
7
+ }
8
+
9
+ function lineHasOptOut(source, index, marker) {
10
+ const lineStart = source.lastIndexOf('\n', index) + 1;
11
+ const lineEnd = source.indexOf('\n', index);
12
+ const line = source.slice(lineStart, lineEnd < 0 ? source.length : lineEnd);
13
+ return line.includes(marker);
14
+ }
15
+
16
+ /**
17
+ * Find high-confidence responsive layout risks shared by Canvas and legacy JSX pages.
18
+ * The checks stay advisory because viewport-owned overlays and fixed-size visualizations
19
+ * can be intentional; authors can add the documented line marker after reviewing one.
20
+ * @param {string} source
21
+ * @returns {Array<{line: number, rule: string, messageKey: string, params?: Array<unknown>}>>}
22
+ */
23
+ function findResponsiveLayoutIssues(source) {
24
+ const text = String(source || '');
25
+ const issues = [];
26
+
27
+ const observerMatch = /new\s+(?:window\.)?ResizeObserver\s*\(/.exec(text);
28
+ if (observerMatch && !/\.\s*(?:disconnect|unobserve)\s*\(/.test(text)) {
29
+ issues.push({
30
+ line: getLine(text, observerMatch.index),
31
+ rule: 'resize-observer-cleanup',
32
+ messageKey: 'publish.lint_resize_observer_cleanup',
33
+ });
34
+ }
35
+
36
+ const viewportMatch = /(?:window\s*\.\s*innerWidth|matchMedia\s*\(\s*['"`]\s*\([^'"`]*(?:min|max)-width)/.exec(text);
37
+ const hasLayoutBranch = /(?:@media|grid-template-columns|gridTemplateColumns|flex-direction|flexDirection|\bmobile\b|\bisMobile\b)/.test(text);
38
+ const hasContainerSignal = /(?:@container|container-type|containerType|ResizeObserver|getBoundingClientRect\s*\(\s*\)\s*\.\s*width|\.\s*clientWidth\b)/.test(text);
39
+ if (
40
+ viewportMatch && hasLayoutBranch && !hasContainerSignal &&
41
+ !text.includes('openyida-responsive-viewport-ok')
42
+ ) {
43
+ issues.push({
44
+ line: getLine(text, viewportMatch.index),
45
+ rule: 'responsive-viewport-only',
46
+ messageKey: 'publish.lint_responsive_viewport_only',
47
+ });
48
+ }
49
+
50
+ const fixedWidthPattern = /(?:^|[\s{;,])width\s*:\s*['"]?(\d{3,})px?['"]?(?=\s*[,;}])/gm;
51
+ let fixedWidthMatch;
52
+ while ((fixedWidthMatch = fixedWidthPattern.exec(text)) !== null) {
53
+ const width = Number(fixedWidthMatch[1]);
54
+ if (
55
+ width >= FIXED_WIDTH_THRESHOLD &&
56
+ !lineHasOptOut(text, fixedWidthMatch.index, 'openyida-responsive-fixed-width-ok')
57
+ ) {
58
+ issues.push({
59
+ line: getLine(text, fixedWidthMatch.index),
60
+ rule: 'responsive-fixed-width',
61
+ messageKey: 'publish.lint_responsive_fixed_width',
62
+ params: [width],
63
+ });
64
+ }
65
+ }
66
+
67
+ const scaleMatch = /(?:transform\s*:\s*[^;\n}]*\bscale\s*\(|\bzoom\s*:)/.exec(text);
68
+ if (scaleMatch && !text.includes('openyida-responsive-scale-ok')) {
69
+ issues.push({
70
+ line: getLine(text, scaleMatch.index),
71
+ rule: 'responsive-page-scale',
72
+ messageKey: 'publish.lint_responsive_page_scale',
73
+ });
74
+ }
75
+
76
+ return issues;
77
+ }
78
+
79
+ module.exports = {
80
+ FIXED_WIDTH_THRESHOLD,
81
+ findResponsiveLayoutIssues,
82
+ };
@@ -612,7 +612,7 @@ const COMMAND_SIDE_EFFECTS = new Map([
612
612
  mutates_yida: true,
613
613
  mutates_local: false,
614
614
  read_actions: ['query', 'get'],
615
- mutating_actions: ['create', 'update', 'delete'],
615
+ mutating_actions: ['create', 'update', 'delete', 'transfer'],
616
616
  })],
617
617
  ['db-seq-fix', sideEffect('mixed', {
618
618
  mutates_yida: true,
@@ -648,7 +648,7 @@ const COMMAND_SIDE_EFFECTS = new Map([
648
648
  mutates_yida: true,
649
649
  mutates_local: true,
650
650
  read_actions: ['url', 'status', 'github status'],
651
- mutating_actions: ['setup', 'dismiss', 'report', 'github star', 'github fork'],
651
+ mutating_actions: ['setup', 'dismiss', 'report', 'github setup --install --confirm', 'github star', 'github fork'],
652
652
  })],
653
653
  ['i18n', sideEffect('mixed', {
654
654
  mutates_yida: true,
@@ -950,7 +950,7 @@ const COMMAND_PERMISSIONS = new Map([
950
950
  ...permissionEntries([
951
951
  'data',
952
952
  ], actionDependentPermission({
953
- preauthorized_actions: ['create', 'update'],
953
+ preauthorized_actions: ['create', 'update', 'transfer'],
954
954
  ask_actions: ['delete'],
955
955
  })),
956
956
 
@@ -1748,12 +1748,13 @@ const COMMAND_GROUPS = [
1748
1748
  id: 'data',
1749
1749
  titleKey: 'help.group_data',
1750
1750
  commands: [
1751
- command('data', ['data'], 'data <query|get|create|update> <resource> ... | delete form <appType> <formUuid> --inst-id <id> --expect-form-name <name> --expect-form-type receipt --confirm [--json]', 'help.cmd_data', {
1751
+ command('data', ['data'], 'data <query|get|create|update|transfer> <resource> ... | delete form <appType> <formUuid> --inst-id <id> --expect-form-name <name> --expect-form-type receipt --confirm [--json]', 'help.cmd_data', {
1752
1752
  managedRun: { scope: 'actions', actions: {
1753
1753
  query: { scope: 'actions', actions: {
1754
1754
  form: { scope: 'app', appPosition: 2 }, subform: { scope: 'app', appPosition: 2 },
1755
1755
  process: { scope: 'app', appPosition: 2 }, 'operation-records': { scope: 'app', appPosition: 2 },
1756
1756
  tasks: { scope: 'app', appPosition: 2 },
1757
+ 'process-tasks': { scope: 'app', appPosition: 2 },
1757
1758
  } },
1758
1759
  get: { scope: 'actions', actions: {
1759
1760
  form: { scope: 'app', appPosition: 2 }, subform: { scope: 'app', appPosition: 2 },
@@ -1773,6 +1774,9 @@ const COMMAND_GROUPS = [
1773
1774
  execute: { scope: 'actions', actions: {
1774
1775
  task: { scope: 'app', appPosition: 2, mutation: { operation: 'execute_task', formUuidOption: '--form-uuid' } },
1775
1776
  } },
1777
+ transfer: { scope: 'actions', actions: {
1778
+ task: { scope: 'app', appPosition: 2, mutation: { operation: 'execute_task', formUuidOption: '--form-uuid' } },
1779
+ } },
1776
1780
  } },
1777
1781
  output: 'json',
1778
1782
  noteKeys: ['help.data_notes', 'query_data.approver_query_help'],
@@ -1787,6 +1791,8 @@ const COMMAND_GROUPS = [
1787
1791
  'openyida data query form APP_XXX FORM_XXX --page 1 --size 20 --search-json \'[{"key":"dateField_due","componentName":"DateField","type":"DOUBLE","operator":"is","value":""}]\'',
1788
1792
  'openyida data create form APP_XXX FORM_XXX --expect-form-name 客户 --expect-form-type receipt --data-json \'{"textField_name":"客户 A","dateField_followUp":1787932800000}\'',
1789
1793
  'openyida data delete form APP_XXX FORM_XXX --inst-id FINST_XXX --expect-form-name 客户 --expect-form-type receipt --confirm --json',
1794
+ 'openyida data query process-tasks APP_XXX --process-inst-id PINST_XXX --json',
1795
+ 'openyida data transfer task APP_XXX --process-inst-id PINST_XXX --form-uuid FORM_XXX --to-user-id USER_ID --expect-form-name "Approval form" --expect-form-type process --json',
1790
1796
  ],
1791
1797
  }),
1792
1798
  command('task-center', ['task-center'], 'task-center <todo|created|done|cc|proxy|capabilities|scaffold|options|inspect|count> [--spec <file.json> --output <file.canvas.jsx>] [options]', 'help.cmd_task_center', {
@@ -2052,11 +2058,13 @@ const COMMAND_GROUPS = [
2052
2058
  requiresLogin: false,
2053
2059
  }),
2054
2060
  command('feedback', ['feedback'], 'feedback <report|github|setup|url|dismiss|status> [options]', 'help.cmd_feedback', { managedRun: { scope: 'actions', actions: { report: { scope: 'local' } } },
2055
- permission: actionDependentPermission({ preauthorized_actions: ['report', 'url', 'status', 'dismiss', 'github status'], ask_actions: ['setup', 'github star', 'github fork'] }),
2061
+ permission: actionDependentPermission({ preauthorized_actions: ['report', 'url', 'status', 'dismiss', 'github status'], ask_actions: ['setup', 'github setup', 'github setup --install --confirm', 'github star', 'github fork'] }),
2056
2062
  requiresLogin: false,
2057
2063
  output: 'text|json',
2058
- examples: ['openyida feedback report --input summary.json --output-dir feedback-draft-001'],
2059
- notes: ['report prepares local review drafts only; no login, source checkout, update check or network submission. github status [--json] checks the authenticated github.com user, Star and personal Fork through an existing gh installation; it performs no writes. github star|fork --confirm [--json] requires the user to explicitly choose that account action. Missing gh/login, unknown status and declined actions never block Issue submission. Already applied actions are reused; writes are single-attempt with readback. No auto-update/install hook, Issue submission, clone or git remote modification. Managed runs permit only offline report preparation.'],
2064
+ examples: ['openyida feedback report --input summary.json --output-dir feedback-draft-001', 'openyida feedback github setup --json', 'openyida feedback github setup --install --confirm --json'],
2065
+ // Keep setup conservative in permission metadata: --install changes the local machine.
2066
+ // The parser distinguishes read-only setup from a separately confirmed installation.
2067
+ notes: ['github setup [--json] detects gh and verifies the current account without installing or logging in. github setup --install --confirm performs one user-approved installation via existing Homebrew (macOS/Linux) or WinGet (Windows), then checks gh again. No manager bootstrap, source changes, automatic retry, upgrade, or automatic login; unsupported environments use official instructions or the web. Browser authorization requires separate consent and public submission still requires content review. report prepares local review drafts only; no login, source checkout, update check or network submission. github status [--json] checks the authenticated github.com user, Star and personal Fork through an existing gh installation; it performs no writes. github star|fork --confirm [--json] requires the user to explicitly choose that account action. Missing gh/login, unknown status and declined actions never block Issue submission. Already applied actions are reused; writes are single-attempt with readback. No auto-update/install hook, Issue submission, clone or git remote modification. Managed runs permit only offline report preparation.'],
2060
2068
  }),
2061
2069
  command('batch', ['batch'], 'batch <file>|--commands "cmd1 ; cmd2" [--stop-on-error] [--json]', 'help.cmd_batch', { managedRun: { scope: 'denied', reason: 'scope_not_audited' },
2062
2070
  output: 'text|json',
@@ -39,7 +39,10 @@ module.exports = {
39
39
  integration_update_v2: {'usage': 'integration update <appType> <formUuid> <processCode> --patch patch.json [--dry-run] [--expect fingerprint] [--publish]'},
40
40
 
41
41
  conditional_actors: { unavailable: 'Conditional actors are unavailable or could not be verified.', invalid: 'Invalid conditional actors: {0}' },
42
- integration_triggers: { invalid: 'Invalid automation trigger: {0}' },
42
+ integration_triggers: {
43
+ invalid: 'Invalid automation trigger: {0}',
44
+ end_required: 'Choose the timer end condition: set schedule.maxCount (1–100) for a run count or schedule.expireDate (expiry in milliseconds) for a specified time. For long-running schedules, choose a distant expiry and show the actual date in the configuration summary.',
45
+ },
43
46
  permission_conditions: { invalid: 'Invalid permission conditions: {0}' },
44
47
  agent: {
45
48
  preflight_cli_detected: 'CLI detected; runtime will discover and report login, protocol and model status.',
@@ -1531,6 +1534,10 @@ Examples:
1531
1534
  lint_setstate_non_timestamp: 'this.setState writes a non-timestamp field. Custom page business state should live in _customState and be updated via forceUpdate()/setCustomState(); this.setState should only carry the timestamp contract field',
1532
1535
  lint_self_binding_missing: 'renderJsx uses this without declaring var self = this;. Add var self = this; at the top of renderJsx and use self inside closures/callbacks to avoid losing this',
1533
1536
  lint_echarts_dom_ready: 'echarts.init is not wrapped in setTimeout; the container may not be mounted yet so the chart may not render. Use setTimeout(function(){ /* echarts.init */ }, 300)',
1537
+ lint_resize_observer_cleanup: 'ResizeObserver has no disconnect()/unobserve() cleanup and may keep measuring after unmount. Release it from the effect or lifecycle cleanup.',
1538
+ lint_responsive_viewport_only: 'Layout changes only from viewport width, so a narrow desktop sidebar, drawer, or iframe may not degrade. Measure the content container with @container or a cleaned-up ResizeObserver. Add openyida-responsive-viewport-ok only for intentional viewport-owned behavior.',
1539
+ lint_responsive_fixed_width: 'A fixed width of %spx may overflow a narrow container. Prefer max-width, minmax(0, 1fr), or local scrolling. Add openyida-responsive-fixed-width-ok only for an intentional fixed canvas.',
1540
+ lint_responsive_page_scale: 'Whole-page scale/zoom was detected. Responsive layouts should reflow content while preserving readable text and touch targets. Add openyida-responsive-scale-ok only for an intentionally scaled local visualization.',
1534
1541
  lint_yida_api_catch: 'this.utils.yida API call has no detected .catch(); add error handling and toast the user',
1535
1542
  lint_echarts_legacy_map_china: 'ECharts 5 no longer supports echarts/map/js/china.js. Load DataV GeoJSON and call echarts.registerMap("china", geoJson) instead',
1536
1543
  lint_echarts_rich_label_formatter: 'ECharts label.formatter returning rich text templates is unstable in Yida custom pages; prefer plain formatter strings or precomputed label text',
@@ -2331,6 +2338,16 @@ module.exports.app_theme = {
2331
2338
  module.exports.help.cmd_app_theme_snapshot = 'Archive application theme settings and CSS (read-only)';
2332
2339
  module.exports.help.cmd_app_theme_restore = 'Check or restore an application theme snapshot (supported exact values only)';
2333
2340
 
2341
+ Object.assign(module.exports.process_tasks || (module.exports.process_tasks = {}), {
2342
+ arguments_invalid: 'Invalid arguments: query requires appType and --process-inst-id; transfer also requires --form-uuid, --to-user-id, --expect-form-name and --expect-form-type process. taskId must be a positive integer; unknown options are not supported.',
2343
+ query_failed: 'Process task query failed; no transfer was performed.',
2344
+ response_invalid: 'The task response structure, task ID or process ownership could not be verified.',
2345
+ not_running: 'The specified task is not running in the target process, or no running task exists; no transfer was performed.',
2346
+ ambiguous: 'Multiple running tasks exist. Query the task list and specify --task-id; no transfer was performed.',
2347
+ rejected: 'The platform rejected the administrator transfer. Check permissions and task status.',
2348
+ result_unknown: 'The administrator transfer result is unknown. Use nextStep to read the tasks; do not automatically retry the transfer.',
2349
+ unverified: 'The transfer was accepted, but readback could not verify the recipient. Use nextStep to read the tasks; do not automatically retry the transfer.',
2350
+ });
2334
2351
  module.exports.data_manage_style = {
2335
2352
  'usage': 'openyida data-manage-style guide [--json]\nopenyida data-manage-style list [--json]\nopenyida data-manage-style generate --app APP_ID --form FORM-ID --style <id> --base-css <snapshot/theme.css> --output <new.css> [--focus balanced|actions] [--field-id <actualId>]... [--emphasize-field <actualId>]... [--tag-field <selectFieldId>]... [--follow-shell] [--json]',
2336
2353
  'data_style_invalid': 'Invalid style parameters; use actual app/form/field IDs and a style returned by list.',
@@ -2427,6 +2444,26 @@ Object.assign(module.exports.help, {'cmd_formula_contracts': 'Show formula forma
2427
2444
  Object.assign(module.exports.formula_v2, {'parallel_formula': 'Use conditions/rules or all:true for parallel branches; expression is currently supported only for route branches.'});
2428
2445
 
2429
2446
  module.exports.feedback_report = {
2447
+ body: {
2448
+ summary: 'Your goal',
2449
+ actual: 'What happened',
2450
+ expected: 'Expected result',
2451
+ incident: 'Environment when the problem occurred',
2452
+ command: 'Related operation',
2453
+ steps: 'How to reproduce',
2454
+ impact: 'Impact',
2455
+ evidence: 'Observed evidence',
2456
+ attempts: 'Attempts and results',
2457
+ cause: 'Cause and confidence',
2458
+ cause_evidence: 'Evidence for assessment',
2459
+ next: 'Next verification',
2460
+ screenshots: 'Screenshots',
2461
+ review_image: 'Review image before sharing',
2462
+ limitations: 'Test limitations',
2463
+ generator: 'Report generator environment (not the incident environment)',
2464
+ unknown: 'Unknown / not verified',
2465
+ draft: 'Local draft — not submitted. Review text and screenshots for customer data, credentials and private information before sharing.',
2466
+ },
2430
2467
  comparison: 'Test pass/fail requires a command, actual result and evidence.',
2431
2468
  screenshots: 'Choose at most five PNG/JPEG/WebP screenshots of at most 10 MiB each.',
2432
2469
  text: 'Feedback text fields must be strings of at most 12000 characters.',
@@ -2514,7 +2551,18 @@ module.exports.task_center = {
2514
2551
  };
2515
2552
 
2516
2553
  module.exports.feedback_github = {
2517
- usage: 'Usage: openyida feedback github <status|star|fork> [--confirm] [--json]',
2554
+ setup_inspect_installation: 'Installation is unverified. Check gh --version, package-manager state or reopen the terminal before deciding to retry; keep the draft.',
2555
+ setup_check_execution: 'gh could not run. Check execution permissions or the local environment; do not reinstall or switch accounts automatically.',
2556
+ setup_confirm_install: 'GitHub CLI can be installed. Explain the plan and obtain consent before openyida feedback github setup --install --confirm --json; the web option remains available.',
2557
+ setup_manual_install: 'Automatic installation is unavailable. Use the official instructions, an existing connector or the web; keep the draft.',
2558
+ setup_ready: 'GitHub CLI and the current account are verified. Resume the draft; confirm public content and required permissions before submission.',
2559
+ setup_browser_login: 'GitHub CLI is available and login is required. With consent, guide browser authorization, then rerun setup --json to verify.',
2560
+ setup_check_account: 'GitHub CLI is available, but the account is unverified. Check network, authorization or rate limits; do not infer a missing account or reinstall.',
2561
+ setup_consent: 'Use --install --confirm only after consent to install GitHub CLI and required dependencies in the package manager default location. Windows accepts WinGet source/package agreements and may need user-approved system permissions. No automatic manager installation, privilege escalation or login.',
2562
+ setup_privacy: 'Installation is not consent to publish. The user authorizes in the browser; never request passwords, codes or tokens. If gh cannot store credentials securely, use the web or a secure connector. Keep account and tool diagnostics out of feedback reports.',
2563
+ usage: 'Usage: openyida feedback github setup [--install --confirm] [--json]; openyida feedback github <status|star|fork> [--confirm] [--json]',
2518
2564
  confirmation: 'Star or Fork requires the user to explicitly choose that action before --confirm. Neither is required to submit an Issue.',
2519
2565
  failed: 'The GitHub action could not be verified. Inspect its status before retrying; this does not block Issue submission.',
2520
2566
  };
2567
+
2568
+ module.exports.process_dynamic_actors = { invalid: 'Invalid process actor configuration. Check details.reason, selection range and actual member fields.' };
@@ -39,7 +39,10 @@ module.exports = {
39
39
  integration_update_v2: {'usage': 'integration update <appType> <formUuid> <processCode> --patch patch.json [--dry-run] [--expect fingerprint] [--publish]'},
40
40
 
41
41
  conditional_actors: { unavailable: 'Conditional actors are unavailable or could not be verified.', invalid: 'Invalid conditional actors: {0}' },
42
- integration_triggers: { invalid: 'Invalid automation trigger: {0}' },
42
+ integration_triggers: {
43
+ invalid: 'Invalid automation trigger: {0}',
44
+ end_required: '请选择定时任务的结束条件:触发次数填写 schedule.maxCount(1–100),指定时间填写 schedule.expireDate(截止时间的毫秒时间戳)。长期运行可选择较远的截止日期,并在配置摘要中展示实际日期。',
45
+ },
43
46
  permission_conditions: { invalid: '数据权限条件无效:{0}' },
44
47
  agent: {
45
48
  preflight_cli_detected: 'CLI 已发现;登录、协议和模型状态由 runtime 检测并上报。',
@@ -1528,6 +1531,10 @@ openyida - 宜搭命令行工具
1528
1531
  lint_setstate_non_timestamp: '检测到 this.setState 写入非 timestamp 字段。业务态应写入 _customState 并调用 forceUpdate()/setCustomState() 触发重渲染;this.setState 仅用于 timestamp 契约字段',
1529
1532
  lint_self_binding_missing: 'renderJsx 内使用了 this 但未声明 var self = this;。请在 renderJsx 开头加入 var self = this;,闭包/回调内改用 self,避免 this 指向丢失',
1530
1533
  lint_echarts_dom_ready: 'echarts.init 未包裹在 setTimeout 中,容器可能尚未挂载导致图表不渲染。建议 setTimeout(function(){ /* echarts.init */ }, 300)',
1534
+ lint_resize_observer_cleanup: 'ResizeObserver 缺少 disconnect()/unobserve() 清理,页面卸载后可能继续测量。请在 effect 或生命周期清理函数中释放 observer。',
1535
+ lint_responsive_viewport_only: '布局只依据视口宽度变化,桌面侧栏、抽屉或 iframe 窄容器可能无法降级。请用 @container 或带清理的 ResizeObserver 测量实际内容容器;若确实是视口级行为,添加 openyida-responsive-viewport-ok 说明。',
1536
+ lint_responsive_fixed_width: '检测到固定宽度 %spx,窄容器可能产生整页横向溢出。请改用 max-width、minmax(0, 1fr) 或局部滚动;确有固定画布需求时添加 openyida-responsive-fixed-width-ok 说明。',
1537
+ lint_responsive_page_scale: '检测到 scale/zoom 整体缩放。响应式布局应重排内容并保留可读字号和点击区域;仅局部可视化确需缩放时添加 openyida-responsive-scale-ok 说明。',
1531
1538
  lint_yida_api_catch: 'this.utils.yida API 调用未检测到 .catch(),请补充错误处理并 toast 给用户',
1532
1539
  lint_echarts_legacy_map_china: 'ECharts 5 已废弃 echarts/map/js/china.js,请加载 DataV GeoJSON 后调用 echarts.registerMap("china", geoJson)',
1533
1540
  lint_echarts_rich_label_formatter: 'ECharts label.formatter 返回 rich text 模板在宜搭自定义页面环境不稳定,建议使用普通 formatter 字符串或预先拼好的标签文本',
@@ -2285,6 +2292,16 @@ module.exports.app_theme = {
2285
2292
  module.exports.help.cmd_app_theme_snapshot = '保存应用主题配置与 CSS 快照(只读)';
2286
2293
  module.exports.help.cmd_app_theme_restore = '检查或恢复应用主题快照(仅支持可精确恢复的配置)';
2287
2294
 
2295
+ Object.assign(module.exports.process_tasks || (module.exports.process_tasks = {}), {
2296
+ arguments_invalid: '参数无效:查询需要 appType 和 --process-inst-id;转交还需要 --form-uuid、--to-user-id、--expect-form-name 和 --expect-form-type process。taskId 必须为正整数,不能使用未知参数。',
2297
+ query_failed: '流程任务查询失败,未执行转交。',
2298
+ response_invalid: '流程任务响应结构、任务 ID 或实例归属无法验证,未继续操作。',
2299
+ not_running: '指定任务不是目标流程的当前运行任务,或流程没有运行中任务,未执行转交。',
2300
+ ambiguous: '流程有多个运行中任务,请查询任务列表并明确传入 --task-id,未执行转交。',
2301
+ rejected: '平台拒绝了管理员转交请求,请核对权限与任务状态。',
2302
+ result_unknown: '管理员转交结果未知,请按 nextStep 只读查询,禁止自动重试转交。',
2303
+ unverified: '转交请求已被接受,但回读未能确认接收人,请按 nextStep 只读查询,禁止自动重试转交。',
2304
+ });
2288
2305
  module.exports.data_manage_style = {
2289
2306
  'usage': 'openyida data-manage-style guide [--json]\nopenyida data-manage-style list [--json]\nopenyida data-manage-style generate --app APP_ID --form FORM-ID --style <id> --base-css <snapshot/theme.css> --output <new.css> [--focus balanced|actions] [--field-id <actualId>]... [--emphasize-field <actualId>]... [--tag-field <selectFieldId>]... [--follow-shell] [--json]',
2290
2307
  'data_style_invalid': '数据管理样式参数无效;请使用真实应用、表单和字段 ID,以及 list 返回的样式。',
@@ -2381,6 +2398,26 @@ Object.assign(module.exports.help, {'cmd_formula_contracts': '查看公式保存
2381
2398
  Object.assign(module.exports.formula_v2, {'parallel_formula': '并行分支使用 conditions/rules 或 all:true;expression 目前只适用于 route 分支。'});
2382
2399
 
2383
2400
  module.exports.feedback_report = {
2401
+ body: {
2402
+ summary: '想完成什么',
2403
+ actual: '实际发生了什么',
2404
+ expected: '希望看到什么结果',
2405
+ incident: '问题发生时的环境',
2406
+ command: '相关操作',
2407
+ steps: '怎样重现',
2408
+ impact: '影响',
2409
+ evidence: '已观察的证据',
2410
+ attempts: '尝试过的方法与结果',
2411
+ cause: '可能的原因及确认程度',
2412
+ cause_evidence: '判断依据',
2413
+ next: '下一步验证',
2414
+ screenshots: '问题截图',
2415
+ review_image: '公开前请检查图片',
2416
+ limitations: '尚未验证的范围',
2417
+ generator: '报告生成环境(不代表问题发生时)',
2418
+ unknown: '未知 / 尚未确认',
2419
+ draft: '本地草稿,尚未提交。请检查文字和截图,确认没有客户数据、凭证或内部信息后再公开。',
2420
+ },
2384
2421
  comparison: '测试通过或失败须提供真实命令、实际结果及证据。',
2385
2422
  screenshots: '截图须为明确选择的 PNG/JPEG/WebP,每张至多 10 MiB,最多 5 张。',
2386
2423
  text: '反馈文本字段须为不超过 12000 字符的字符串。',
@@ -2468,7 +2505,18 @@ module.exports.task_center = {
2468
2505
  };
2469
2506
 
2470
2507
  module.exports.feedback_github = {
2471
- usage: '用法:openyida feedback github <status|star|fork> [--confirm] [--json]',
2508
+ setup_inspect_installation: '安装结果尚未核实。先检查 gh --version、包管理器状态或重新打开终端,再决定是否重试;草稿仍保留。',
2509
+ setup_check_execution: 'gh 暂时无法运行。请检查执行权限或本机环境;不要重复安装或更换账号。',
2510
+ setup_confirm_install: '可安装 GitHub CLI。先说明安装计划并取得用户同意,再执行 openyida feedback github setup --install --confirm --json;也可使用网页。',
2511
+ setup_manual_install: '当前没有可用的自动安装方式。可查看官方安装说明、使用已有连接器或网页,草稿仍保留。',
2512
+ setup_ready: 'GitHub CLI 和当前账号已验证。继续原草稿,提交前仍需核对公开内容和所需权限。',
2513
+ setup_browser_login: 'GitHub CLI 已可用,需要登录。用户同意后引导浏览器授权,完成后再次运行 setup --json 核实。',
2514
+ setup_check_account: 'GitHub CLI 已可用,但当前账号尚未核实。先检查网络、授权或限流;不要据此判断用户没有账号或要求重新安装。',
2515
+ setup_consent: '仅在用户同意安装 GitHub CLI 及其必要依赖后使用 --install --confirm。使用包管理器默认位置;Windows 安装会接受 WinGet 来源和软件协议,可能需要用户批准系统权限。不自动安装包管理器、提权或登录。',
2516
+ setup_privacy: '安装不代表同意公开提交。浏览器授权由用户完成;不索取密码、验证码或 Token。若 gh 无法安全保存凭证,改用网页或安全连接器;账号和工具诊断不写入反馈报告。',
2517
+ usage: '用法:openyida feedback github setup [--install --confirm] [--json]; openyida feedback github <status|star|fork> [--confirm] [--json]',
2472
2518
  confirmation: 'Star 或 Fork 需要用户明确选择后再传入 --confirm;提交 Issue 不要求这两项操作。',
2473
2519
  failed: 'GitHub 操作未能核实完成,请先查询状态;这不影响提交 Issue。',
2474
2520
  };
2521
+
2522
+ module.exports.process_dynamic_actors = { invalid: '流程人员来源配置无效,请按 details.reason 检查来源、范围与真实成员字段。' };
@@ -8,6 +8,7 @@
8
8
  * query form / get form / create form / update form / delete form / query subform
9
9
  * query process / get process / create process / update process
10
10
  * query operation-records / execute task / query tasks
11
+ * query process-tasks / transfer task (administrator)
11
12
  */
12
13
 
13
14
  'use strict';
@@ -22,6 +23,7 @@ const { queryByCurrentApprover, validateApproverOptions } = require('./process-a
22
23
  const { buildComponentAliasMaps } = require('../app/get-schema');
23
24
  const { readFormMode } = require('../app/services/form-mode-service');
24
25
  const { fetchFormPageList } = require('../app/form-navigation');
26
+ const processTasks = require('../process/process-tasks');
25
27
 
26
28
  const USAGE = `openyida data - Unified Yida data CLI
27
29
 
@@ -39,6 +41,8 @@ Usage:
39
41
  openyida data create process <appType> <formUuid> --process-code <processCode> (--data-json <JSON>|--data-file .cache/openyida/data.json) --expect-form-name <name> --expect-form-type process [--dept-id ID] [--resolve-aliases]
40
42
  openyida data update process <appType> --process-inst-id <processInstanceId> --form-uuid <formUuid> (--data-json <JSON>|--data-file .cache/openyida/data.json) --expect-form-name <name> --expect-form-type process [--resolve-aliases]
41
43
  openyida data query operation-records <appType> --process-inst-id <processInstanceId>
44
+ openyida data query process-tasks <appType> --process-inst-id <processInstanceId> [--json]
45
+ openyida data transfer task <appType> --process-inst-id <processInstanceId> --form-uuid <formUuid> --to-user-id <userId> --expect-form-name <name> --expect-form-type process [--remark <text>] [--task-id <taskId>] [--json]
42
46
  openyida data execute task <appType> --task-id <taskId> --process-inst-id <processInstanceId> --form-uuid <formUuid> --expect-form-name <name> --expect-form-type process --out-result <AGREE|DISAGREE> --remark <text> [--data-json JSON|--data-file .cache/openyida/data.json] [--resolve-aliases] [--no-execute-expressions y]
43
47
 
44
48
  openyida data query tasks <appType> --type <todo|created|done|submitted|cc> [--transport app-v1|app-query] [--page N] [--size N] [--keyword TEXT] [--normalized] [--process-codes JSON] [--instance-status STATUS]
@@ -69,6 +73,8 @@ const SUPPORTED_DATA_COMMANDS = new Set([
69
73
  'query:operation-records',
70
74
  'execute:task',
71
75
  'query:tasks',
76
+ 'query:process-tasks',
77
+ 'transfer:task',
72
78
  ]);
73
79
 
74
80
  const MUTATION_DATA_COMMANDS = new Set([
@@ -78,6 +84,7 @@ const MUTATION_DATA_COMMANDS = new Set([
78
84
  'create:process',
79
85
  'update:process',
80
86
  'execute:task',
87
+ 'transfer:task',
81
88
  ]);
82
89
 
83
90
  function fail(message) {
@@ -149,6 +156,10 @@ function validateDataCommandBeforeAuth(action, resource, positionals, options) {
149
156
  );
150
157
  }
151
158
 
159
+ if ((action === 'query' && resource === 'process-tasks') || action === 'transfer') {
160
+ processTasks.validateArguments(positionals, options, action === 'transfer');
161
+ }
162
+
152
163
  if (MUTATION_DATA_COMMANDS.has(`${action}:${resource}`)) {
153
164
  requireOption(options, 'expect_form_name');
154
165
  requireOption(options, 'expect_form_type');
@@ -203,7 +214,7 @@ function ensureSession() {
203
214
  return authRef;
204
215
  }
205
216
 
206
- function parseCliOptions(tokens) {
217
+ function parseCliOptions(tokens, strict = false) {
207
218
  const positionals = [];
208
219
  const options = {};
209
220
 
@@ -211,6 +222,9 @@ function parseCliOptions(tokens) {
211
222
  const token = tokens[i];
212
223
  if (token.startsWith('--')) {
213
224
  const key = token.slice(2).replace(/-/g, '_');
225
+ if (strict && Object.prototype.hasOwnProperty.call(options, key)) {
226
+ parseError(t('process_tasks.arguments_invalid'));
227
+ }
214
228
  const next = tokens[i + 1];
215
229
  if (next && !next.startsWith('--')) {
216
230
  options[key] = next;
@@ -1512,6 +1526,24 @@ async function queryTasks(positionals, options, session) {
1512
1526
  printResult(options.normalized ? { success: true, content: normalized } : result);
1513
1527
  }
1514
1528
 
1529
+ async function transferProcessTask(positionals, options, session) {
1530
+ const [appType] = positionals;
1531
+ const target = await requireExpectedFormTarget(session, appType, options.form_uuid, options);
1532
+ const record = await readProcessInstance(session, appType, options.process_inst_id);
1533
+ requireInstanceTarget(record, target, options.process_inst_id,
1534
+ ['processInstanceId', 'processInstId', 'instanceId']);
1535
+ const instanceStatus = record.processInstanceStatus || record.instanceStatus;
1536
+ if (instanceStatus && instanceStatus !== 'RUNNING') {
1537
+ dataError('DATA_PROCESS_TASK_NOT_RUNNING', t('process_tasks.not_running'), {
1538
+ retryable: false, retrySafe: true, sideEffectState: 'none',
1539
+ });
1540
+ }
1541
+ printResult(await processTasks.transferTask(createYidaClient({ authRef: session }), {
1542
+ appType, formUuid: options.form_uuid, processInstanceId: options.process_inst_id,
1543
+ taskId: options.task_id, toUserId: options.to_user_id, remark: options.remark,
1544
+ }));
1545
+ }
1546
+
1515
1547
  async function run(args) {
1516
1548
  if (args.length < 2) {
1517
1549
  parseError('缺少必填参数 action 或 resource');
@@ -1519,7 +1551,8 @@ async function run(args) {
1519
1551
 
1520
1552
  const action = args[0];
1521
1553
  const resource = args[1];
1522
- const { positionals, options } = parseCliOptions(args.slice(2));
1554
+ const strict = action === 'transfer' || (action === 'query' && resource === 'process-tasks');
1555
+ const { positionals, options } = parseCliOptions(args.slice(2), strict);
1523
1556
 
1524
1557
  if (
1525
1558
  action === 'query' &&
@@ -1551,6 +1584,11 @@ async function run(args) {
1551
1584
  if (action === 'query' && resource === 'operation-records') {return queryOperationRecords(positionals, options, session);}
1552
1585
  if (action === 'execute' && resource === 'task') {return executeTask(positionals, options, session);}
1553
1586
  if (action === 'query' && resource === 'tasks') {return queryTasks(positionals, options, session);}
1587
+ if (action === 'query' && resource === 'process-tasks') {
1588
+ return printResult(await processTasks.queryProcessTasks(
1589
+ createYidaClient({ authRef: session }), positionals[0], options.process_inst_id));
1590
+ }
1591
+ if (action === 'transfer' && resource === 'task') {return transferProcessTask(positionals, options, session);}
1554
1592
 
1555
1593
  dataError('DATA_COMMAND_UNSUPPORTED', t('query_data.command_unsupported', action, resource));
1556
1594
  }
@@ -60,6 +60,7 @@ const SAMPLES = {
60
60
  'canvas-theme': 'canvas-theme-provider.template.jsx',
61
61
  'canvas-navigation': 'canvas-navigation.jsx',
62
62
  'canvas-view-state': 'canvas-view-state.jsx',
63
+ 'canvas-responsive-layout': 'canvas-responsive-layout.jsx',
63
64
  'canvas-admin-entry': 'canvas-admin-entry.jsx',
64
65
  'canvas-nav-side': 'canvas-nav/side.jsx',
65
66
  'canvas-nav-top': 'canvas-nav/top.jsx',
@@ -109,6 +110,7 @@ const SAMPLE_OUTPUT_FILENAMES = {
109
110
  'openyida-page-template/form-open-container': 'form-open-container.jsx',
110
111
  'openyida-page-template/canvas-dialog': 'canvas-dialog.jsx',
111
112
  'openyida-page-template/canvas-theme': 'canvas-theme.jsx',
113
+ 'openyida-page-template/canvas-responsive-layout': 'canvas-responsive-layout.jsx',
112
114
  'yida-design/app-theme': 'app-theme.css',
113
115
  };
114
116
 
@@ -116,6 +118,7 @@ const SAMPLE_HINTS = {
116
118
  'openyida-page-template/canvas-admin-entry': '已包含统一跳转 helper;在 CanvasThemeProvider 内渲染 CanvasAdminWorkbenchButton,填写当前 appType 与真实 workbenchFormUuid。身份读取当前应用 loginUser.isAppAdmin,未知时隐藏;默认不跳开发后台或猜测管理首页。',
117
119
  'openyida-page-template/canvas-navigation': '先从资源回读填写 appType、目标类型与页面 ID;本页 Tab 用 selectView,独立前台用 custom,管理入口用 page,表单入口接 openForm;按钮和链接共用 buildCanvasPageUrl。',
118
120
  'openyida-page-template/canvas-theme': '以 CanvasThemeProvider 包住业务组件;Tabs 用于内容切换,Segmented/Radio 用于筛选,Button 用于动作。默认轻底选中态与可读文字,controls 可供自绘控件复用;避免内层固定色覆盖。保留内置加载遮罩防闪边样式;旧页面需更新 Provider 并重新发布。',
121
+ 'openyida-page-template/canvas-responsive-layout': '合并 useContainerLayout 与 ResponsiveLayout;按实际内容容器重排筛选栏和主辅面板,宽表仅局部滚动,图表按 data-chart-width resize。业务状态放在布局壳之上,断点切换不得修改 key 或重挂载。',
119
122
  'openyida-page-template/canvas-nav-top': '顶部默认贴顶通栏;长页先合并 canvas-nav-content,CanvasNav 传 headerOnly,有首屏背景时传 overlay;悬浮外观仅显式 floating=true。',
120
123
  'openyida-page-template/canvas-nav-content': '合并 CanvasNavigationContent;长页用 layout=document,CanvasNav 传 headerOnly/overlay;默认 sticky,受宿主限制时用 navigationPosition=fixed。工作区用 workspace,宿主已分配高度时传 height。',
121
124
  'openyida-page-template/canvas-nav-data': '页内展示用 mode=local(key/viewKey/targetType=local),不请求平台菜单;platform 需真实资源 ID;independent 或声明 access 时必须接入真实 resolveAccess。保留 PRD 顺序与分组。',
@@ -51,6 +51,7 @@ function printUsage() {
51
51
  openyida feedback setup <appType> [--name "OpenYida 体验反馈"] [--path /o/openyida-feedback] [--open|--no-open]
52
52
  openyida feedback setup --create-app [--app-name "OpenYida 体验反馈"] [--name "OpenYida 体验反馈"]
53
53
  openyida feedback report --input <summary.json> --output-dir <new-directory>
54
+ openyida feedback github setup [--install --confirm] [--json]
54
55
  openyida feedback github <status|star|fork> [--confirm] [--json]
55
56
  openyida feedback url [--tool Codex] [--model gpt-5] [--command publish] [--diagnostics "..."]
56
57
  openyida feedback dismiss --today|--forever|--reset
@@ -58,7 +59,7 @@ function printUsage() {
58
59
 
59
60
  说明:
60
61
  ${t('feedback_report.help')}
61
- setup 会在宜搭创建一个公开反馈表单,并写入本地 .cache/openyida/feedback/config.json。
62
+ feedback setup 会在宜搭创建一个公开反馈表单,并写入本地 .cache/openyida/feedback/config.json。
62
63
  url 只生成带脱敏元数据的填写链接,不提交任何网络请求。
63
64
  dismiss/status 只读写本地提醒状态。
64
65
  `);