yidaconnector 2026.6.11

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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +383 -0
  3. package/bin/yida.js +670 -0
  4. package/lib/app/form-navigation.js +58 -0
  5. package/lib/app/get-schema.js +538 -0
  6. package/lib/auth/auth.js +294 -0
  7. package/lib/auth/cdp-browser-login.js +390 -0
  8. package/lib/auth/codex-login.js +71 -0
  9. package/lib/auth/login.js +475 -0
  10. package/lib/auth/org.js +363 -0
  11. package/lib/auth/qr-login.js +1563 -0
  12. package/lib/core/chalk.js +384 -0
  13. package/lib/core/check-update.js +82 -0
  14. package/lib/core/cli-error.js +39 -0
  15. package/lib/core/command-manifest.js +106 -0
  16. package/lib/core/env-cmd.js +545 -0
  17. package/lib/core/env-manager.js +601 -0
  18. package/lib/core/env.js +287 -0
  19. package/lib/core/i18n.js +177 -0
  20. package/lib/core/locales/ar.js +805 -0
  21. package/lib/core/locales/de.js +805 -0
  22. package/lib/core/locales/en.js +1623 -0
  23. package/lib/core/locales/es.js +805 -0
  24. package/lib/core/locales/fr.js +805 -0
  25. package/lib/core/locales/hi.js +805 -0
  26. package/lib/core/locales/ja.js +1197 -0
  27. package/lib/core/locales/ko.js +807 -0
  28. package/lib/core/locales/pt.js +805 -0
  29. package/lib/core/locales/vi.js +805 -0
  30. package/lib/core/locales/zh-HK.js +1233 -0
  31. package/lib/core/locales/zh.js +1584 -0
  32. package/lib/core/query-data.js +781 -0
  33. package/lib/core/redact.js +100 -0
  34. package/lib/core/utils.js +799 -0
  35. package/lib/core/yida-client.js +117 -0
  36. package/package.json +94 -0
  37. package/project/config.json +4 -0
  38. package/project/pages/src/demo-birthday-game.oyd.jsx +832 -0
  39. package/project/pages/src/demo-chip-insight.oyd.jsx +983 -0
  40. package/project/pages/src/demo-compat-smoke.oyd.jsx +58 -0
  41. package/project/pages/src/demo-crm-batch-entry.oyd.jsx +805 -0
  42. package/project/pages/src/demo-crm-dashboard.oyd.jsx +677 -0
  43. package/project/pages/src/demo-future-vision-2026.oyd.jsx +1102 -0
  44. package/project/pages/src/demo-ppt.oyd.jsx +1192 -0
  45. package/project/pages/src/demo-salary-calculator.oyd.jsx +904 -0
  46. package/project/pages/src/yidaconnector-knowledge-doc.oyd.jsx +1714 -0
  47. package/project/prd/demo-birthday-game.md +39 -0
  48. package/project/prd/demo-crm.md +463 -0
  49. package/project/prd/demo-dingtalk-ai-solution-center.md +425 -0
  50. package/project/prd/demo-future-vision-2026.md +78 -0
  51. package/project/prd/demo-salary-calculator.md +101 -0
  52. package/scripts/build-skills-package.js +406 -0
  53. package/scripts/check-syntax.js +59 -0
  54. package/scripts/demo-dws.sh +106 -0
  55. package/scripts/e2e-real/cleanup.js +67 -0
  56. package/scripts/e2e-real/fixtures/form-fields.json +18 -0
  57. package/scripts/e2e-real/full-runner.js +1566 -0
  58. package/scripts/e2e-real/runner.js +293 -0
  59. package/scripts/e2e-real/skill-coverage.js +115 -0
  60. package/scripts/generate-command-docs.js +109 -0
  61. package/scripts/nightly-smoke.js +134 -0
  62. package/scripts/postinstall.js +545 -0
  63. package/scripts/solution-center-runner.js +368 -0
  64. package/scripts/validate-ci.sh +50 -0
  65. package/scripts/validate-command-manifest.js +119 -0
  66. package/scripts/validate-package-size.js +78 -0
  67. package/scripts/validate-skills.js +247 -0
  68. package/scripts/validate-structure.js +66 -0
  69. package/yida-skills/SKILL.md +163 -0
  70. package/yida-skills/references/yida-api.md +1309 -0
  71. package/yida-skills/skills/large-file-write/SKILL.md +91 -0
  72. package/yida-skills/skills/large-file-write/references/write-patterns.md +149 -0
  73. package/yida-skills/skills/large-file-write/scripts/write.js +157 -0
  74. package/yida-skills/skills/yida-data-management/SKILL.md +252 -0
  75. package/yida-skills/skills/yida-data-management/references/api-matrix.md +49 -0
  76. package/yida-skills/skills/yida-data-management/references/data-format-guide.md +159 -0
  77. package/yida-skills/skills/yida-data-management/references/verified-endpoints.md +62 -0
  78. package/yida-skills/skills/yida-login/SKILL.md +159 -0
  79. package/yida-skills/skills/yida-logout/SKILL.md +67 -0
@@ -0,0 +1,247 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const ROOT = path.resolve(__dirname, '..');
9
+ const SKILLS_ROOT = path.join(ROOT, 'yida-skills');
10
+ const SKILLS_DIR = path.join(SKILLS_ROOT, 'skills');
11
+ const INDEX_FILE = path.join(SKILLS_ROOT, 'SKILL.md');
12
+ const MAX_RECOMMENDED_LINES = 500;
13
+
14
+ const errors = [];
15
+ const warnings = [];
16
+
17
+ function toRelative(filePath) {
18
+ return path.relative(ROOT, filePath).split(path.sep).join('/');
19
+ }
20
+
21
+ function readText(filePath) {
22
+ return fs.readFileSync(filePath, 'utf8');
23
+ }
24
+
25
+ function collectMarkdownFiles(dir, files) {
26
+ if (!fs.existsSync(dir)) {
27
+ return;
28
+ }
29
+
30
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
31
+ for (const entry of entries) {
32
+ const fullPath = path.join(dir, entry.name);
33
+ if (entry.isDirectory()) {
34
+ collectMarkdownFiles(fullPath, files);
35
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
36
+ files.push(fullPath);
37
+ }
38
+ }
39
+ }
40
+
41
+ function parseFrontmatter(content) {
42
+ const lines = content.split(/\r?\n/);
43
+ if (lines[0] !== '---') {
44
+ return null;
45
+ }
46
+
47
+ const endIndex = lines.findIndex(function(line, index) {
48
+ return index > 0 && line === '---';
49
+ });
50
+
51
+ if (endIndex < 0) {
52
+ return null;
53
+ }
54
+
55
+ return lines.slice(1, endIndex).join('\n');
56
+ }
57
+
58
+ function frontmatterField(frontmatter, fieldName) {
59
+ const match = frontmatter.match(new RegExp('^' + fieldName + ':\\s*(.*)$', 'm'));
60
+ if (!match) {
61
+ return null;
62
+ }
63
+
64
+ return match[1].trim();
65
+ }
66
+
67
+ function validateSkillFrontmatter(skillDirName, skillFile) {
68
+ const content = readText(skillFile);
69
+ const frontmatter = parseFrontmatter(content);
70
+
71
+ if (!frontmatter) {
72
+ errors.push(toRelative(skillFile) + ': missing YAML frontmatter');
73
+ return;
74
+ }
75
+
76
+ const name = frontmatterField(frontmatter, 'name');
77
+ const description = frontmatterField(frontmatter, 'description');
78
+
79
+ if (!name) {
80
+ errors.push(toRelative(skillFile) + ': missing frontmatter field "name"');
81
+ } else if (name !== skillDirName) {
82
+ errors.push(toRelative(skillFile) + ': frontmatter name must match directory name "' + skillDirName + '"');
83
+ }
84
+
85
+ if (!description) {
86
+ errors.push(toRelative(skillFile) + ': missing frontmatter field "description"');
87
+ }
88
+
89
+ const lineCount = content.split(/\r?\n/).length;
90
+ if (lineCount > MAX_RECOMMENDED_LINES) {
91
+ warnings.push(
92
+ toRelative(skillFile) + ': ' + lineCount + ' lines, consider moving rarely used details into references/'
93
+ );
94
+ }
95
+ }
96
+
97
+ function validateRootSkillFrontmatter() {
98
+ const content = readText(INDEX_FILE);
99
+ const frontmatter = parseFrontmatter(content);
100
+
101
+ if (!frontmatter) {
102
+ errors.push(toRelative(INDEX_FILE) + ': missing YAML frontmatter');
103
+ return;
104
+ }
105
+
106
+ const fieldNames = frontmatter.split(/\r?\n/).filter(function(line) {
107
+ return /^[a-zA-Z0-9_-]+:\s*/.test(line);
108
+ }).map(function(line) {
109
+ return line.split(':')[0];
110
+ });
111
+
112
+ const allowedFields = ['name', 'description'];
113
+ const unexpectedFields = fieldNames.filter(function(fieldName) {
114
+ return !allowedFields.includes(fieldName);
115
+ });
116
+
117
+ if (unexpectedFields.length > 0) {
118
+ errors.push(toRelative(INDEX_FILE) + ': Wukong root skill frontmatter must only contain name and description');
119
+ }
120
+
121
+ const name = frontmatterField(frontmatter, 'name');
122
+ if (name !== 'yidaconnector') {
123
+ errors.push(toRelative(INDEX_FILE) + ': root skill name must be "yidaconnector"');
124
+ }
125
+
126
+ const description = frontmatterField(frontmatter, 'description');
127
+ if (!description) {
128
+ errors.push(toRelative(INDEX_FILE) + ': missing frontmatter field "description"');
129
+ } else {
130
+ const normalizedDescription = frontmatter.replace(/^description:\s*>?\s*/m, '').trim();
131
+ if (!/不要触发|不触发|DO NOT TRIGGER/i.test(normalizedDescription)) {
132
+ errors.push(toRelative(INDEX_FILE) + ': root description must include a do-not-trigger boundary');
133
+ }
134
+ }
135
+ }
136
+
137
+ function validateIndexEntry(skillDirName, skillFile) {
138
+ if (!fs.existsSync(INDEX_FILE)) {
139
+ errors.push(toRelative(INDEX_FILE) + ': missing root skill index');
140
+ return;
141
+ }
142
+
143
+ const indexText = readText(INDEX_FILE);
144
+ const expectedPath = 'skills/' + skillDirName + '/SKILL.md';
145
+ if (!indexText.includes(expectedPath)) {
146
+ errors.push(toRelative(skillFile) + ': missing from yida-skills/SKILL.md index as ' + expectedPath);
147
+ }
148
+ }
149
+
150
+ function isExternalLink(target) {
151
+ return /^(https?:|mailto:|tel:|app:\/\/|plugin:\/\/|#)/i.test(target);
152
+ }
153
+
154
+ function normalizeMarkdownTarget(rawTarget) {
155
+ const trimmed = rawTarget.trim().replace(/^<|>$/g, '');
156
+ const targetWithoutTitle = trimmed.split(/\s+/)[0];
157
+ const targetWithoutAnchor = targetWithoutTitle.split('#')[0];
158
+
159
+ if (!targetWithoutAnchor) {
160
+ return null;
161
+ }
162
+
163
+ try {
164
+ return decodeURIComponent(targetWithoutAnchor);
165
+ } catch (_error) {
166
+ return targetWithoutAnchor;
167
+ }
168
+ }
169
+
170
+ function validateMarkdownLinks(markdownFile) {
171
+ const content = readText(markdownFile);
172
+ const linkPattern = /!?\[[^\]\n]*\]\(([^)\n]+)\)/g;
173
+ let match = linkPattern.exec(content);
174
+
175
+ while (match) {
176
+ const rawTarget = match[1];
177
+ const normalizedTarget = normalizeMarkdownTarget(rawTarget);
178
+
179
+ if (normalizedTarget && !isExternalLink(normalizedTarget)) {
180
+ if (/^file:/i.test(normalizedTarget) || path.isAbsolute(normalizedTarget)) {
181
+ errors.push(
182
+ toRelative(markdownFile) + ': non-portable markdown link "' + rawTarget + '"'
183
+ );
184
+ match = linkPattern.exec(content);
185
+ continue;
186
+ }
187
+
188
+ const absoluteTarget = path.resolve(path.dirname(markdownFile), normalizedTarget);
189
+ if (!fs.existsSync(absoluteTarget)) {
190
+ errors.push(
191
+ toRelative(markdownFile) + ': broken markdown link "' + rawTarget + '"'
192
+ );
193
+ }
194
+ }
195
+
196
+ match = linkPattern.exec(content);
197
+ }
198
+ }
199
+
200
+ function run() {
201
+ if (!fs.existsSync(SKILLS_DIR)) {
202
+ errors.push(toRelative(SKILLS_DIR) + ': missing skills directory');
203
+ } else {
204
+ validateRootSkillFrontmatter();
205
+
206
+ const skillDirNames = fs.readdirSync(SKILLS_DIR).filter(function(name) {
207
+ const fullPath = path.join(SKILLS_DIR, name);
208
+ return fs.statSync(fullPath).isDirectory();
209
+ }).sort();
210
+
211
+ for (const skillDirName of skillDirNames) {
212
+ const skillFile = path.join(SKILLS_DIR, skillDirName, 'SKILL.md');
213
+ if (!fs.existsSync(skillFile)) {
214
+ errors.push('yida-skills/skills/' + skillDirName + ': missing SKILL.md');
215
+ continue;
216
+ }
217
+
218
+ validateSkillFrontmatter(skillDirName, skillFile);
219
+ validateIndexEntry(skillDirName, skillFile);
220
+ }
221
+ }
222
+
223
+ const markdownFiles = [];
224
+ collectMarkdownFiles(SKILLS_ROOT, markdownFiles);
225
+ for (const markdownFile of markdownFiles.sort()) {
226
+ validateMarkdownLinks(markdownFile);
227
+ }
228
+
229
+ if (warnings.length > 0) {
230
+ console.warn('Skill validation warnings:');
231
+ for (const warning of warnings) {
232
+ console.warn(' warn ' + warning);
233
+ }
234
+ }
235
+
236
+ if (errors.length > 0) {
237
+ console.error('Skill validation failed:');
238
+ for (const error of errors) {
239
+ console.error(' error ' + error);
240
+ }
241
+ process.exit(1);
242
+ }
243
+
244
+ console.log('Skill validation OK: checked ' + markdownFiles.length + ' markdown files');
245
+ }
246
+
247
+ run();
@@ -0,0 +1,66 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const requiredDirs = ['bin', 'lib', 'project', 'yida-skills', 'scripts'];
5
+ const requiredFiles = [
6
+ 'bin/yida.js',
7
+ 'package.json',
8
+ 'project/config.json',
9
+ 'README.md',
10
+ 'LICENSE',
11
+ 'CONTRIBUTING.md',
12
+ '.eslintrc.json',
13
+ ];
14
+
15
+ let hasError = false;
16
+
17
+ for (const dir of requiredDirs) {
18
+ if (!fs.existsSync(dir)) {
19
+ console.error('Missing directory: ' + dir);
20
+ hasError = true;
21
+ }
22
+ }
23
+
24
+ for (const file of requiredFiles) {
25
+ if (!fs.existsSync(file)) {
26
+ console.error('Missing file: ' + file);
27
+ hasError = true;
28
+ }
29
+ }
30
+
31
+ if (hasError) {
32
+ process.exit(1);
33
+ }
34
+
35
+ // Validate package.json engines field
36
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
37
+ const nodeEngine = packageJson.engines && packageJson.engines.node;
38
+ if (!nodeEngine) {
39
+ console.error('package.json missing engines.node field');
40
+ process.exit(1);
41
+ }
42
+ console.log('engines.node: ' + nodeEngine);
43
+
44
+ const skillsDir = 'yida-skills/skills';
45
+ if (fs.existsSync(skillsDir)) {
46
+ const skills = fs.readdirSync(skillsDir).filter(function(name) {
47
+ return fs.statSync(path.join(skillsDir, name)).isDirectory();
48
+ });
49
+ console.log('yida-skills sub-skills: ' + skills.length);
50
+ }
51
+
52
+ function countJsFiles(dir) {
53
+ let count = 0;
54
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
55
+ for (let i = 0; i < entries.length; i++) {
56
+ const entry = entries[i];
57
+ if (entry.isDirectory()) {
58
+ count += countJsFiles(path.join(dir, entry.name));
59
+ } else if (entry.name.endsWith('.js')) {
60
+ count++;
61
+ }
62
+ }
63
+ return count;
64
+ }
65
+ console.log('lib/ modules: ' + countJsFiles('lib'));
66
+ console.log('Project structure OK');
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: yidaconnector
3
+ description: >
4
+ 宜搭数据查询与登录态管理技能。通过有 AI Coding 能力的智能体(悟空/Claude/Open Code 等)查询宜搭表单、流程、任务数据并管理登录态。
5
+ 包含表单/流程/任务/子表单数据查询、登录、登出、环境检测等能力。
6
+ 当用户提到"宜搭"、"yida"、"查询数据"、"表单数据"、"流程数据"、"登录宜搭"等关键词时,使用此技能;以下情况不要触发:只是讨论通用前端/后端代码、非宜搭平台产品、或只需要解释概念而不操作宜搭资源。
7
+ ---
8
+
9
+ # 宜搭数据查询与登录态管理指南
10
+
11
+ ## 概述
12
+
13
+ 本技能通过有 AI Coding 能力的智能体(悟空/Claude/Open Code 等)查询宜搭低代码平台的表单、流程、任务数据,并管理登录态。
14
+
15
+ 所有操作通过 **`yidaconnector`** 命令行工具统一执行,无需关心脚本路径或运行环境差异。
16
+
17
+ **登录态说明**:所有命令自动读取 `.cache/cookies.json`,首次运行或 Cookie 失效时自动触发登录流程,也可手动执行登录命令。
18
+
19
+ ---
20
+
21
+ ## 环境依赖
22
+
23
+ | 依赖 | 版本 | 用途 |
24
+ |------|------|------|
25
+ | Node.js | ≥ 16 | 运行 yidaconnector |
26
+
27
+ ```bash
28
+ # 安装 yidaconnector(首次使用前执行)
29
+ npm install -g yidaconnector
30
+
31
+ # 更新 yidaconnector 到最新版本
32
+ npm install -g yidaconnector@latest
33
+ ```
34
+
35
+ ---
36
+
37
+ ## ⚡ 首要步骤:检测运行环境(必须先执行)
38
+
39
+ **在执行任何宜搭操作前,必须先运行环境检测命令**,确认当前 AI 工具环境和登录态:
40
+
41
+ ```bash
42
+ yidaconnector env --json
43
+ yidaconnector login --check-only --json
44
+ ```
45
+
46
+ `yidaconnector env --json` 用于确认当前 AI 工具、项目根目录、配置文件和登录态拆解项;`yidaconnector login --check-only --json` 只读取本地登录缓存,不触发登录、不打开浏览器、不创建任何资源。
47
+
48
+ 若用户明确要求登录某个宜搭入口 URL,登录命令必须携带该 URL 或对应环境 flag。例如 `https://yida-group.alibaba-inc.com/` 是阿里内网宜搭,应执行 `yidaconnector login https://yida-group.alibaba-inc.com/` 或 `yidaconnector login --alibaba`,不要退化成裸 `yidaconnector login`,否则会落到默认公有云 `www.aliwork.com`。
49
+
50
+ **输出解读**:
51
+
52
+ | 字段 | 说明 |
53
+ |------|------|
54
+ | AI 工具检测 | 显示当前活跃的 AI 工具(悟空/OpenCode/Aone Copilot 等) |
55
+ | 当前生效环境 | 显示项目根目录路径 |
56
+ | 登录态检测 | 显示是否已登录、域名、组织 ID |
57
+
58
+ > **若显示"未登录",先执行 `yidaconnector login`。Codex 中默认返回内置浏览器 handoff:用 Browser Use 打开 `login_url`,让钉钉/宜搭页面承接扫码和组织选择。页面登录完成后必须再次执行 `yidaconnector login --check-only --json` 验证缓存写入。**
59
+
60
+ ---
61
+
62
+ ## 何时使用
63
+
64
+ 当用户提出以下需求时,使用本技能:
65
+ - 查询宜搭表单数据、流程实例、任务列表、子表单明细
66
+ - 查看/创建/更新表单或流程数据
67
+ - 执行流程任务(同意/驳回)
68
+ - 管理宜搭登录态(登录/退出/切换组织/切换环境)
69
+
70
+ ---
71
+
72
+ ## 子技能速查
73
+
74
+ > 每个子技能均有独立的 SKILL.md。执行时先选定一个最匹配的子技能,只读取该子技能文档;references 按文档提示按需读取,避免一次性加载全量文档。
75
+
76
+ | 技能 | SKILL.md 路径 | 用途 | 典型命令 |
77
+ |------|--------------|------|---------|
78
+ | `yida-data-management` | `skills/yida-data-management/SKILL.md` | 表单/子表/流程/任务数据查询与变更 | `yidaconnector data query form <appType> <formUuid>` |
79
+ | `yida-login` | `skills/yida-login/SKILL.md` | 登录态管理(通常自动触发) | `yidaconnector login` |
80
+ | `yida-logout` | `skills/yida-logout/SKILL.md` | 退出登录 / 切换账号 | `yidaconnector logout` |
81
+ | `large-file-write` | `skills/large-file-write/SKILL.md` | 大文件可靠写入辅助技能 | 详见 SKILL.md |
82
+
83
+ ---
84
+
85
+ ## 关键规则
86
+
87
+ ### 1. 执行子技能前必须读取其 SKILL.md
88
+
89
+ 每个子技能的详细参数、注意事项、示例均在其 SKILL.md 中。**执行任何子技能前,必须先读取对应的 SKILL.md**,不要凭记忆猜测参数格式。
90
+
91
+ ### 2. 性能与正确性规则(必须遵守)
92
+
93
+ - **只读必要文档**:先根据用户意图选定 1 个主技能;只有该技能明确要求时,才读取对应 `references/` 文档,禁止一次性读取全部技能文档。
94
+ - **优先复用缓存**:已知的 `appType`、`formUuid`、`formInstId`、`fieldId` 优先复用;缺失或不确定时再查询。
95
+ - **避免无效重试**:同一命令失败后,先根据错误信息检查登录态、组织、参数和字段 ID;不要无修改地连续重试超过 1 次。
96
+ - **分页注意**:宜搭 API 单页最大 100 条,`--all` 会自动翻页拉取全量;数据量大时留意 `pagesFetched` 与 `totalCount`。
97
+
98
+ ### 3. corpId 一致性检查(必须遵守)
99
+
100
+ 查询数据前,**必须对比目标应用的 corpId 与 `.cache/cookies.json` 中的 corpId 是否一致**:
101
+
102
+ - **一致** → 继续执行
103
+ - **不一致** → 询问用户:重新登录到正确组织,还是切换组织?
104
+
105
+ ### 4. 临时文件规范
106
+
107
+ 所有临时文件(cookies、查询结果、字段映射、一次性脚本等)**必须写在项目根目录的 `.cache/` 文件夹中**,不要写到仓库根目录,也不要写在系统其他位置。
108
+
109
+ 推荐路径:
110
+
111
+ | 工件类型 | 推荐位置 |
112
+ |---------|---------|
113
+ | 查询结果 / 数据导出 | `.cache/yidaconnector/data-export/` |
114
+ | 字段 ID 映射 | `.cache/<项目名>-schema.json` |
115
+ | 一次性 Python / JS 执行脚本 | `.cache/yidaconnector/scripts/` |
116
+
117
+ > 若只是为了调用 `yidaconnector` 命令临时生成的 `*.json`、`*.js`、`*.py`、`*.csv` 文件,一律放入 `.cache/yidaconnector/` 子目录。
118
+
119
+ ---
120
+
121
+ ## 宜搭应用 URL 规则
122
+
123
+ | 页面类型 | URL 格式 |
124
+ |---------|---------|
125
+ | 应用首页 | `{base_url}/{appType}/workbench` |
126
+ | 表单提交页 | `{base_url}/{appType}/submission/{formUuid}` |
127
+ | 表单详情页 | `{base_url}/{appType}/formDetail/{formUuid}?formInstId={formInstId}` |
128
+ | 表单详情页(编辑模式) | `{base_url}/{appType}/formDetail/{formUuid}?formInstId={formInstId}&mode=edit` |
129
+
130
+ > 所有地址拼接 `&corpid={corpId}` 可自动切换到对应组织。
131
+
132
+ ---
133
+
134
+ ## 常见问题
135
+
136
+ **Q:查询时提示登录失效?**
137
+
138
+ 重新登录后再查询:
139
+ ```bash
140
+ yidaconnector login
141
+ yidaconnector data query form <appType> <formUuid>
142
+ ```
143
+
144
+ **Q:如何切换到其他组织?**
145
+
146
+ ```bash
147
+ yidaconnector org list
148
+ yidaconnector org switch --corp-id <corpId>
149
+ ```
150
+
151
+ **Q:如何切换到私有化/国际版环境?**
152
+
153
+ ```bash
154
+ yidaconnector env list
155
+ yidaconnector env switch <name>
156
+ # 或登录时直接指定
157
+ yidaconnector login --intl
158
+ yidaconnector login --alibaba
159
+ ```
160
+
161
+ **Q:完整 API 参考在哪里?**
162
+
163
+ 宜搭 API 完整字段与端点参考见 [references/yida-api.md](references/yida-api.md)。