openyida 2026.6.22-beta.0 → 2026.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -3
- package/bin/yida.js +41 -21
- package/lib/app/create-form.js +34 -4
- package/lib/app/er.js +679 -0
- package/lib/app/nav-group.js +85 -0
- package/lib/app/page-compat.js +241 -2
- package/lib/app/page-linter.js +101 -6
- package/lib/app/publish.js +11 -0
- package/lib/auth/auth.js +25 -14
- package/lib/auth/login.js +63 -7
- package/lib/auth/qr-login.js +12 -0
- package/lib/conversation/collector.js +2 -0
- package/lib/core/command-manifest.js +5 -2
- package/lib/core/env.js +5 -1
- package/lib/core/locales/ar.js +29 -22
- package/lib/core/locales/de.js +29 -22
- package/lib/core/locales/en.js +28 -1
- package/lib/core/locales/es.js +29 -22
- package/lib/core/locales/fr.js +29 -22
- package/lib/core/locales/hi.js +29 -22
- package/lib/core/locales/ja.js +30 -22
- package/lib/core/locales/ko.js +29 -22
- package/lib/core/locales/pt.js +29 -22
- package/lib/core/locales/vi.js +29 -22
- package/lib/core/locales/zh-HK.js +9 -1
- package/lib/core/locales/zh.js +28 -1
- package/lib/core/utils.js +93 -15
- package/lib/formula/evaluate.js +75 -0
- package/lib/integration/integration-api.js +11 -7
- package/lib/integration/integration-create.js +303 -67
- package/lib/integration/integration-process-builder.js +106 -24
- package/lib/integration/integration-spec-builder.js +977 -0
- package/lib/integration/integration-view-builder.js +53 -11
- package/package.json +8 -2
- package/scripts/build-skills-package.js +47 -3
- package/scripts/e2e-real/skill-coverage.js +1 -0
- package/scripts/eval/VERIFY.md +169 -0
- package/scripts/eval/agent.js +148 -0
- package/scripts/eval/config.js +276 -0
- package/scripts/eval/dashboard/index.html +389 -0
- package/scripts/eval/dashboard/server.js +344 -0
- package/scripts/eval/eval.config.json +8 -0
- package/scripts/eval/generate.js +362 -0
- package/scripts/eval/guardrail.js +130 -0
- package/scripts/eval/manifest.js +117 -0
- package/scripts/eval/report.js +262 -0
- package/scripts/eval/routing.js +190 -0
- package/scripts/eval/runner.js +318 -0
- package/scripts/eval/scenarios/generation/generation-core.json +32 -0
- package/scripts/eval/scenarios/routing-core.json +86 -0
- package/scripts/eval/score.js +197 -0
- package/scripts/eval/screenshot.js +193 -0
- package/scripts/postinstall.js +10 -2
- package/scripts/validate-package-size.js +1 -1
- package/scripts/validate-skills.js +14 -2
- package/yida-skills/SKILL.md +128 -308
- package/yida-skills/references/development-rules.md +80 -0
- package/yida-skills/references/field-and-url-reference.md +42 -0
- package/yida-skills/references/setup-and-env.md +90 -0
- package/yida-skills/skills/large-file-write/SKILL.md +1 -1
- package/yida-skills/skills/yida-agent-center/SKILL.md +1 -7
- package/yida-skills/skills/yida-app/SKILL.md +47 -10
- package/yida-skills/skills/yida-app-permission/SKILL.md +1 -8
- package/yida-skills/skills/yida-basic-info/SKILL.md +1 -1
- package/yida-skills/skills/yida-business-rule/SKILL.md +1 -1
- package/yida-skills/skills/yida-chart/SKILL.md +114 -1509
- package/yida-skills/skills/yida-connector/SKILL.md +1 -6
- package/yida-skills/skills/yida-connector-safe-actions/SKILL.md +1 -1
- package/yida-skills/skills/yida-corp-efficiency/SKILL.md +2 -3
- package/yida-skills/skills/yida-corp-manager/SKILL.md +1 -7
- package/yida-skills/skills/yida-create-app/SKILL.md +1 -1
- package/yida-skills/skills/yida-create-form-page/SKILL.md +69 -7
- package/yida-skills/skills/yida-create-page/SKILL.md +1 -6
- package/yida-skills/skills/yida-create-process/SKILL.md +1 -5
- package/yida-skills/skills/yida-custom-page/SKILL.md +21 -321
- package/yida-skills/skills/yida-custom-page/references/coding-guide.md +38 -0
- package/yida-skills/skills/yida-custom-page/references/runtime-guardrails.md +55 -0
- package/yida-skills/skills/yida-dashboard/SKILL.md +5 -1
- package/yida-skills/skills/yida-data-management/SKILL.md +1 -6
- package/yida-skills/skills/yida-data-source-connectors/SKILL.md +2 -6
- package/yida-skills/skills/yida-density/SKILL.md +1 -1
- package/yida-skills/skills/yida-export-conversation/SKILL.md +2 -5
- package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +2 -5
- package/yida-skills/skills/yida-form-detail/SKILL.md +1 -3
- package/yida-skills/skills/yida-form-permission/SKILL.md +1 -6
- package/yida-skills/skills/yida-formula/SKILL.md +1 -19
- package/yida-skills/skills/yida-formula-evaluate/SKILL.md +1 -9
- package/yida-skills/skills/yida-get-schema/SKILL.md +1 -5
- package/yida-skills/skills/yida-integration/SKILL.md +93 -7
- package/yida-skills/skills/yida-login/SKILL.md +6 -5
- package/yida-skills/skills/yida-logout/SKILL.md +1 -1
- package/yida-skills/skills/yida-nav-group/SKILL.md +26 -1
- package/yida-skills/skills/yida-openyida-publish-guard/SKILL.md +88 -0
- package/yida-skills/skills/yida-page-config/SKILL.md +1 -5
- package/yida-skills/skills/yida-ppt-slider/SKILL.md +98 -1400
- package/yida-skills/skills/yida-ppt-slider/references/dark-tech-theme.md +204 -0
- package/yida-skills/skills/yida-ppt-slider/references/echarts-race-example.md +330 -0
- package/yida-skills/skills/yida-process-rule/SKILL.md +1 -5
- package/yida-skills/skills/yida-publish-page/SKILL.md +2 -4
- package/yida-skills/skills/yida-report/SKILL.md +3 -6
- package/yida-skills/skills/yida-table-form/SKILL.md +2 -6
- package/yida-skills/skills/yida-voc/SKILL.md +1 -9
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ OpenYida detects the active agent environment, workspace path, login state, and
|
|
|
69
69
|
openyida login
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
In Codex, QoderWork, Qoder, Wukong, Claude Code, OpenCode, Cursor, and other detected AI tools, OpenYida first tries local Chrome/Edge/Chromium CDP when no valid cached login exists. If local CDP is unavailable, it falls back to an AI-dialog QR handoff. The agent should render `qr_image_markdown` or paste `agent_response_markdown` directly in the conversation so the QR code is visible, then run `poll_command` after the user scans it with DingTalk. If image rendering is unavailable, fall back to `qr_url`. The explicit `openyida login --browser` command still prefers CDP first and uses Playwright as an optional browser fallback.
|
|
72
|
+
In Codex, QoderWork, Qoder, Wukong, Claude Code, MuleRun, OpenCode, Cursor, and other detected AI tools, OpenYida first tries local Chrome/Edge/Chromium CDP when no valid cached login exists. If local CDP is unavailable, it falls back to an AI-dialog QR handoff. The agent should render `qr_image_markdown` or paste `agent_response_markdown` directly in the conversation so the QR code is visible, then run `poll_command` after the user scans it with DingTalk. If image rendering is unavailable, fall back to `qr_url`. The explicit `openyida login --browser` command still prefers CDP first and uses Playwright as an optional browser fallback.
|
|
73
73
|
|
|
74
74
|
When the user names a target Yida entry URL, pass it to the login command so OpenYida can select the matching environment and cookie file. For example, Alibaba intranet Yida uses `cookies-alibaba.json`:
|
|
75
75
|
|
|
@@ -126,6 +126,7 @@ export PATH="$HOME/.real/.bin/node/bin:$PATH"
|
|
|
126
126
|
|------|---------|
|
|
127
127
|
| [Codex](https://openai.com/codex/) | Full support |
|
|
128
128
|
| [Claude Code](https://claude.ai/code) | Full support |
|
|
129
|
+
| [MuleRun](https://mulerun.com) | Full support |
|
|
129
130
|
| [Aone Copilot](https://copilot.code.alibaba-inc.com) | Full support |
|
|
130
131
|
| [OpenCode](https://opencode.ai) | Full support |
|
|
131
132
|
| [Cursor](https://cursor.com/) | Full support |
|
|
@@ -263,6 +264,59 @@ Useful options:
|
|
|
263
264
|
|
|
264
265
|
Use `npm run test:e2e:real:cleanup` to list recorded disposable resources. OpenYida does not yet expose a safe app/form deletion command, so cleanup is intentionally a registry-backed audit step rather than an automatic destructive action.
|
|
265
266
|
|
|
267
|
+
### Skill Evaluation Harness
|
|
268
|
+
|
|
269
|
+
The E2E paths above prove the *CLI* works. The eval harness under `scripts/eval/` measures whether the *agent* still routes natural-language requests to the right sub-skill and produces good output after you edit `yida-skills/SKILL.md`. It is the feedback loop for harness engineering.
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Routing eval — "did it pick the right sub-skill?" No real resources, no login.
|
|
273
|
+
# Drives a headless `claude -p` agent with each scenario prompt and checks
|
|
274
|
+
# the selected sub-skill against the golden set.
|
|
275
|
+
npm run eval:routing
|
|
276
|
+
|
|
277
|
+
# Tool-pipeline baseline (end-to-end) — wraps the real-environment runner for one
|
|
278
|
+
# sub-skill, adds guardrail assertions, screenshots the published page, and writes a
|
|
279
|
+
# human scoring template. Runs deterministic CLI commands (no agent) so it serves as
|
|
280
|
+
# a control that proves the build→publish→screenshot→score plumbing itself works.
|
|
281
|
+
# Requires OPENYIDA_E2E=1 and a valid cookie cache.
|
|
282
|
+
OPENYIDA_E2E=1 npm run eval:e2e -- --skill yida-dashboard --screenshot
|
|
283
|
+
|
|
284
|
+
# Same, plus automatic screenshot scoring via the local multimodal `claude -p`.
|
|
285
|
+
OPENYIDA_E2E=1 npm run eval:e2e -- --skill yida-dashboard --screenshot --auto-score
|
|
286
|
+
|
|
287
|
+
# Real-generation eval — "can one sentence really build a usable app?" Feeds a
|
|
288
|
+
# natural-language request ("帮我创建一个订单管理系统") to a headless `claude -p`
|
|
289
|
+
# that actually reads the openyida skill and runs the CLI to build a real app, then
|
|
290
|
+
# reuses the screenshot + scoring + report pipeline. Creates real 宜搭 resources, so
|
|
291
|
+
# it needs OPENYIDA_E2E=1 + an authenticated agent. Unlike the deterministic baseline
|
|
292
|
+
# above, here the agent self-orchestrates.
|
|
293
|
+
OPENYIDA_E2E=1 npm run eval:generate -- --screenshot
|
|
294
|
+
|
|
295
|
+
# Run all three in one pass (routing + tool-pipeline baseline + real generation).
|
|
296
|
+
OPENYIDA_E2E=1 npm run eval:all -- --skill yida-dashboard --screenshot
|
|
297
|
+
|
|
298
|
+
# Optional: a zero-dependency local web console (buttons + live streamed output)
|
|
299
|
+
# that runs the tasks above on click. Binds to 127.0.0.1 only; tasks are a fixed
|
|
300
|
+
# whitelist. Use the Node version you start it with, so run `nvm use 20` first.
|
|
301
|
+
npm run eval:dashboard # http://127.0.0.1:4500
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Configuration precedence is `CLI flag > env (OPENYIDA_EVAL_*) > scripts/eval/eval.config.json > defaults`.
|
|
305
|
+
|
|
306
|
+
| Flag | Purpose |
|
|
307
|
+
|------|---------|
|
|
308
|
+
| `--mode e2e\|routing\|generate\|all` | Which evals to run (default `e2e`; `all` = routing + tool-pipeline baseline + real generation) |
|
|
309
|
+
| `--skill <name>` | Restrict the e2e run to one sub-skill; stages are reverse-looked-up from the `SKILL_COVERAGE` matrix |
|
|
310
|
+
| `--stages a,b` | Explicit stage list, overriding the skill reverse-lookup |
|
|
311
|
+
| `--screenshot` / `--no-screenshot` | Capture the published page (default on; skipped gracefully if Playwright is absent) |
|
|
312
|
+
| `--auto-score` / `--no-auto-score` | Score screenshots with the local `claude -p` agent (default off → human template only) |
|
|
313
|
+
| `--scenarios <dir>` | Routing golden-set directory (default `scripts/eval/scenarios`) |
|
|
314
|
+
| `--gen-scenarios <dir>` | Real-generation golden-set directory (default `scripts/eval/scenarios/generation`) |
|
|
315
|
+
|
|
316
|
+
Results are written back into the existing `acceptance-manifest.json` under a new `eval` section (guardrails, screenshots, scores) plus two sibling artifacts: a `scoring.md` human-scoring template and a self-contained `eval-report.html` visual report (screenshots inlined as base64, so the single file opens anywhere). Routing results land in `project/.cache/eval/routing-report.json`; generation results (with their own `scoring.md` + `eval-report.html`) land in `project/.cache/eval/generate/gen-<timestamp>/`. The harness degrades gracefully: a missing Playwright skips screenshots (enable with `npm install --no-save playwright && npx playwright install chromium`), and a missing `claude` CLI skips auto-scoring while keeping the human template. A guardrail failure (for example a resource-creating command issued before a successful `login --check-only`) fails the run.
|
|
317
|
+
|
|
318
|
+
A zero-dependency local dashboard (`npm run eval:dashboard`, then open `http://127.0.0.1:4500`) drives these runs from buttons and streams output live; its "📊 查看最新报告" button opens the most recent `eval-report.html`.
|
|
319
|
+
|
|
266
320
|
### Connectors, Integrations, and Reports
|
|
267
321
|
|
|
268
322
|
```bash
|
|
@@ -301,7 +355,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
301
355
|
| `openyida corp-efficiency [overview\|details\|detail\|groups\|notify] [options] [--open\|--no-open]` | Query enterprise efficiency overview and detail reports |
|
|
302
356
|
| `openyida create-app "<name>"\|--name <name> [options] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a Yida app |
|
|
303
357
|
| `openyida update-app <appType> [--name "..."] [--layout slide\|ver] [--theme deepBlue]` | Update app info |
|
|
304
|
-
| `openyida nav-group <list\|create\|rename\|delete\|move\|hide\|show> <appType> ...` | Manage app sidebar navigation groups |
|
|
358
|
+
| `openyida nav-group <list\|create\|rename\|delete\|move\|order\|hide\|show> <appType> ...` | Manage app sidebar navigation groups |
|
|
305
359
|
| `openyida app-permission <get\|set\|add\|remove\|search-user> ...` | Manage app primary, data, and developer admins |
|
|
306
360
|
| `openyida i18n <overview\|config\|languages\|list\|upsert\|delete\|translate\|translate-all\|upgrade> <appType> ...` | Manage app multilingual copy and language config |
|
|
307
361
|
| `openyida export <appType> [output]` | Export app (generate migration package) |
|
|
@@ -322,6 +376,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
322
376
|
| `openyida list-forms <appType> [--keyword <text>]` | List forms/pages in an app |
|
|
323
377
|
| `openyida aggregate-table <list\|create-empty\|inspect\|preview\|save\|publish\|status> <appType> ...` | Manage aggregate tables (virtualView) |
|
|
324
378
|
| `openyida get-schema <appType> <formUuid\|--all>` | Get one form Schema or all form Schemas |
|
|
379
|
+
| `openyida er <appType> [--format mermaid\|json] [--output file] [--include-system] [--include-pages]` | Export app entity relationship diagram |
|
|
325
380
|
| `openyida create-page <appType> "<name>" [--mode dashboard] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
|
|
326
381
|
| `openyida generate-page <template>` | Generate page from curated template |
|
|
327
382
|
| `openyida build-page <sourceFile> [--output file\|--write]` | Build Yida-compatible page source |
|
|
@@ -389,7 +444,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
389
444
|
|
|
390
445
|
| Command | Description |
|
|
391
446
|
|---------|-------------|
|
|
392
|
-
| `openyida integration create <appType>
|
|
447
|
+
| `openyida integration create <appType> ... [--spec file.json]` | Create integration automation flow |
|
|
393
448
|
| `openyida integration list <appType> [--form-uuid <uuid>] [--status y\|n] [--json]` | List integration automation flows |
|
|
394
449
|
| `openyida integration enable <appType> <formUuid> <processCode>` | Enable integration automation flow |
|
|
395
450
|
| `openyida integration disable <appType> <formUuid> <processCode>` | Disable integration automation flow |
|
package/bin/yida.js
CHANGED
|
@@ -27,6 +27,8 @@ function isAgentEnvironment(env) {
|
|
|
27
27
|
env.CODEX_HOME ||
|
|
28
28
|
env.CLAUDE_CODE ||
|
|
29
29
|
env.CLAUDE_CODE_ENTRYPOINT ||
|
|
30
|
+
env.MULERUN_CHAT_ID ||
|
|
31
|
+
env.MULE_DATA_DIR ||
|
|
30
32
|
env.OPENCODE ||
|
|
31
33
|
env.OPENCODE_CLIENT ||
|
|
32
34
|
env.QODER_IDE ||
|
|
@@ -212,6 +214,16 @@ function handleFirstRunGuide() {
|
|
|
212
214
|
function printLoginResult(result) {
|
|
213
215
|
noteLoginCommandResult(result);
|
|
214
216
|
|
|
217
|
+
if (!result) {
|
|
218
|
+
console.log(JSON.stringify({
|
|
219
|
+
ok: false,
|
|
220
|
+
status: 'login_failed',
|
|
221
|
+
can_auto_use: false,
|
|
222
|
+
error: 'login_failed',
|
|
223
|
+
}));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
215
227
|
if (result && (result.status === 'need_qr_scan' || result.status === 'need_corp_selection')) {
|
|
216
228
|
console.log(JSON.stringify(result));
|
|
217
229
|
return;
|
|
@@ -243,6 +255,11 @@ function printLoginResult(result) {
|
|
|
243
255
|
return;
|
|
244
256
|
}
|
|
245
257
|
|
|
258
|
+
if (result.status && result.status !== 'ok' && !result.csrf_token) {
|
|
259
|
+
console.log(JSON.stringify(result));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
246
263
|
const summary = {
|
|
247
264
|
ok: true,
|
|
248
265
|
base_url: result && result.base_url,
|
|
@@ -311,9 +328,11 @@ function shouldUsePlaywrightFallbackInAgentLogin() {
|
|
|
311
328
|
return hasDesktopEnvironment() || process.env.OPENYIDA_AGENT_PLAYWRIGHT_FALLBACK === '1';
|
|
312
329
|
}
|
|
313
330
|
|
|
314
|
-
function
|
|
315
|
-
const {
|
|
316
|
-
return
|
|
331
|
+
function shouldUseLocalBrowserLogin(options = {}) {
|
|
332
|
+
const { hasLocalBrowserLoginCapability } = require('../lib/auth/login');
|
|
333
|
+
return hasLocalBrowserLoginCapability({
|
|
334
|
+
playwrightFallback: options.playwrightFallback,
|
|
335
|
+
});
|
|
317
336
|
}
|
|
318
337
|
|
|
319
338
|
function shouldUseCodexQrLogin(cliArgs) {
|
|
@@ -540,6 +559,7 @@ async function main() {
|
|
|
540
559
|
case 'login': {
|
|
541
560
|
const { checkLoginOnly } = require('../lib/auth/login');
|
|
542
561
|
const loginArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
|
|
562
|
+
const { isInjectedAuthMode } = require('../lib/core/utils');
|
|
543
563
|
if (loginArgs.includes('--agent-poll') || loginArgs.includes('--codex-poll')) {
|
|
544
564
|
const sessionFile = getArgValue(loginArgs, '--agent-poll') || getArgValue(loginArgs, '--codex-poll');
|
|
545
565
|
const { pollCodexQrLogin } = require('../lib/auth/qr-login');
|
|
@@ -554,9 +574,12 @@ async function main() {
|
|
|
554
574
|
corpId: getArgValue(loginArgs, '--corp-id'),
|
|
555
575
|
});
|
|
556
576
|
printLoginResult(result);
|
|
557
|
-
} else if (loginArgs
|
|
577
|
+
} else if (loginArgs.includes('--check-only')) {
|
|
558
578
|
const result = checkLoginOnly({ includeSecrets: loginArgs.includes('--with-cookies') });
|
|
559
579
|
console.log(JSON.stringify(result, null, 2));
|
|
580
|
+
} else if (isInjectedAuthMode()) {
|
|
581
|
+
const result = checkLoginOnly({ includeSecrets: true });
|
|
582
|
+
printLoginResult(result);
|
|
560
583
|
} else if (shouldUseCodexQrLogin(loginArgs)) {
|
|
561
584
|
const { startCodexQrLogin } = require('../lib/auth/qr-login');
|
|
562
585
|
const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
|
|
@@ -578,26 +601,17 @@ async function main() {
|
|
|
578
601
|
if (cachedResult.status === 'ok') {
|
|
579
602
|
printLoginResult(cachedResult);
|
|
580
603
|
} else {
|
|
581
|
-
const { detectActiveTool } = require('../lib/core/utils');
|
|
582
|
-
const activeTool = detectActiveTool();
|
|
583
604
|
const { interactiveLogin } = require('../lib/auth/login');
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
605
|
+
const playwrightFallback = shouldUsePlaywrightFallbackInAgentLogin();
|
|
606
|
+
const browserResult = shouldUseLocalBrowserLogin({ playwrightFallback })
|
|
607
|
+
? interactiveLogin({ playwrightFallback })
|
|
608
|
+
: null;
|
|
587
609
|
if (browserResult) {
|
|
588
610
|
printLoginResult(browserResult);
|
|
589
611
|
} else {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
const { codexLogin } = require('../lib/auth/codex-login');
|
|
594
|
-
const result = await codexLogin({ tool: activeTool.tool });
|
|
595
|
-
printLoginResult(result);
|
|
596
|
-
} else {
|
|
597
|
-
const { startCodexQrLogin } = require('../lib/auth/qr-login');
|
|
598
|
-
const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
|
|
599
|
-
printLoginResult(result);
|
|
600
|
-
}
|
|
612
|
+
const { startCodexQrLogin } = require('../lib/auth/qr-login');
|
|
613
|
+
const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
|
|
614
|
+
printLoginResult(result);
|
|
601
615
|
}
|
|
602
616
|
}
|
|
603
617
|
} else if (shouldUseBrowserHandoffLogin(loginArgs)) {
|
|
@@ -615,7 +629,7 @@ async function main() {
|
|
|
615
629
|
printLoginResult(cachedResult);
|
|
616
630
|
break;
|
|
617
631
|
}
|
|
618
|
-
if (
|
|
632
|
+
if (shouldUseLocalBrowserLogin({ playwrightFallback: true })) {
|
|
619
633
|
const { interactiveLogin } = require('../lib/auth/login');
|
|
620
634
|
const browserResult = interactiveLogin({ playwrightFallback: true });
|
|
621
635
|
if (browserResult) {
|
|
@@ -758,6 +772,12 @@ async function main() {
|
|
|
758
772
|
break;
|
|
759
773
|
}
|
|
760
774
|
|
|
775
|
+
case 'er': {
|
|
776
|
+
const { run } = require('../lib/app/er');
|
|
777
|
+
await run(args);
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
|
|
761
781
|
case 'formula': {
|
|
762
782
|
const subCommand = args[0];
|
|
763
783
|
const subArgs = args.slice(1);
|
package/lib/app/create-form.js
CHANGED
|
@@ -66,6 +66,7 @@ const { buildYidaI18n, normalizeYidaLocale, resolveContentLocale } = require('..
|
|
|
66
66
|
const { banner, step, label, success, fail, warn, info, error, result, usage, hint, listItem } = require('../core/chalk');
|
|
67
67
|
const { parseOpenOption, withBrowserHandoff } = require('../core/browser-handoff');
|
|
68
68
|
const { default: babelTransform } = require('../core/babel-transform');
|
|
69
|
+
const { normalizeFormulaFieldRefs } = require('../formula/evaluate');
|
|
69
70
|
|
|
70
71
|
// ── 选项类字段类型 ───────────────────────────────────
|
|
71
72
|
const OPTION_FIELD_TYPES = ['RadioField', 'SelectField', 'CheckboxField', 'MultiSelectField'];
|
|
@@ -3601,13 +3602,34 @@ function jsString(value) {
|
|
|
3601
3602
|
return JSON.stringify(value === undefined ? '' : value);
|
|
3602
3603
|
}
|
|
3603
3604
|
|
|
3605
|
+
function compileCustomValidateSource(source) {
|
|
3606
|
+
const funcSource = String(source || 'function validateRule(value) { return true; }').trim();
|
|
3607
|
+
return 'function main(){\n \n "use strict";\n\nvar __compiledFunc__ = '
|
|
3608
|
+
+ funcSource
|
|
3609
|
+
+ ';\n return __compiledFunc__.apply(this, arguments);\n }';
|
|
3610
|
+
}
|
|
3611
|
+
|
|
3604
3612
|
function normalizeCustomValidateParam(param) {
|
|
3605
|
-
if (param && typeof param === 'object' && param.type === '
|
|
3606
|
-
return
|
|
3613
|
+
if (param && typeof param === 'object' && param.type === 'js') {
|
|
3614
|
+
const source = param.source || 'function validateRule(value) { return true; }';
|
|
3615
|
+
return {
|
|
3616
|
+
compiled: param.compiled || compileCustomValidateSource(source),
|
|
3617
|
+
source: source,
|
|
3618
|
+
type: 'js',
|
|
3619
|
+
error: param.error || {},
|
|
3620
|
+
};
|
|
3621
|
+
}
|
|
3622
|
+
let funcSource = typeof param === 'string' ? param
|
|
3623
|
+
: (param && typeof param === 'object' && param.type === 'JSExpression') ? String(param.value || '')
|
|
3624
|
+
: String(param || '');
|
|
3625
|
+
if (!funcSource || !/function/.test(funcSource)) {
|
|
3626
|
+
funcSource = 'function validateRule(value) { return true; }';
|
|
3607
3627
|
}
|
|
3608
3628
|
return {
|
|
3609
|
-
|
|
3610
|
-
|
|
3629
|
+
compiled: compileCustomValidateSource(funcSource),
|
|
3630
|
+
source: funcSource,
|
|
3631
|
+
type: 'js',
|
|
3632
|
+
error: {},
|
|
3611
3633
|
};
|
|
3612
3634
|
}
|
|
3613
3635
|
|
|
@@ -3617,6 +3639,9 @@ function buildCustomValidateExpressionParam(rule) {
|
|
|
3617
3639
|
|
|
3618
3640
|
function buildCustomValidateParam(rule) {
|
|
3619
3641
|
if (rule.type === 'customValidate' && rule.param) {
|
|
3642
|
+
if (typeof rule.param === 'object' && rule.param.type === 'js') {
|
|
3643
|
+
return rule.param;
|
|
3644
|
+
}
|
|
3620
3645
|
return typeof rule.param === 'object' && rule.param.type === 'JSExpression'
|
|
3621
3646
|
? String(rule.param.value || '')
|
|
3622
3647
|
: String(rule.param);
|
|
@@ -4357,6 +4382,11 @@ async function saveSchemaAndUpdateConfig(authRef, appType, formUuid, schema, ver
|
|
|
4357
4382
|
const saveStep = stepOffset || 4;
|
|
4358
4383
|
const configStep = saveStep + 1;
|
|
4359
4384
|
|
|
4385
|
+
const fixedRefs = normalizeFormulaFieldRefs(schema);
|
|
4386
|
+
if (fixedRefs > 0) {
|
|
4387
|
+
info(t('create_form.formula_prefix_fixed', fixedRefs));
|
|
4388
|
+
}
|
|
4389
|
+
|
|
4360
4390
|
step(saveStep, t('create_form.step_save_schema', saveStep));
|
|
4361
4391
|
info(t('create_form.sending_save'));
|
|
4362
4392
|
|