openyida 2026.6.22-beta.1 → 2026.7.7-1
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 +56 -2
- package/bin/yida.js +40 -22
- 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 +36 -17
- package/lib/auth/login.js +88 -13
- package/lib/auth/qr-login.js +12 -0
- package/lib/core/command-manifest.js +5 -2
- package/lib/core/env.js +23 -5
- 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 +268 -20
- 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 +6 -1
- 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 +205 -0
- package/scripts/eval/screenshot.js +193 -0
- 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
|
@@ -264,6 +264,59 @@ Useful options:
|
|
|
264
264
|
|
|
265
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.
|
|
266
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
|
+
|
|
267
320
|
### Connectors, Integrations, and Reports
|
|
268
321
|
|
|
269
322
|
```bash
|
|
@@ -302,7 +355,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
302
355
|
| `openyida corp-efficiency [overview\|details\|detail\|groups\|notify] [options] [--open\|--no-open]` | Query enterprise efficiency overview and detail reports |
|
|
303
356
|
| `openyida create-app "<name>"\|--name <name> [options] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a Yida app |
|
|
304
357
|
| `openyida update-app <appType> [--name "..."] [--layout slide\|ver] [--theme deepBlue]` | Update app info |
|
|
305
|
-
| `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 |
|
|
306
359
|
| `openyida app-permission <get\|set\|add\|remove\|search-user> ...` | Manage app primary, data, and developer admins |
|
|
307
360
|
| `openyida i18n <overview\|config\|languages\|list\|upsert\|delete\|translate\|translate-all\|upgrade> <appType> ...` | Manage app multilingual copy and language config |
|
|
308
361
|
| `openyida export <appType> [output]` | Export app (generate migration package) |
|
|
@@ -323,6 +376,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
323
376
|
| `openyida list-forms <appType> [--keyword <text>]` | List forms/pages in an app |
|
|
324
377
|
| `openyida aggregate-table <list\|create-empty\|inspect\|preview\|save\|publish\|status> <appType> ...` | Manage aggregate tables (virtualView) |
|
|
325
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 |
|
|
326
380
|
| `openyida create-page <appType> "<name>" [--mode dashboard] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
|
|
327
381
|
| `openyida generate-page <template>` | Generate page from curated template |
|
|
328
382
|
| `openyida build-page <sourceFile> [--output file\|--write]` | Build Yida-compatible page source |
|
|
@@ -390,7 +444,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
|
|
|
390
444
|
|
|
391
445
|
| Command | Description |
|
|
392
446
|
|---------|-------------|
|
|
393
|
-
| `openyida integration create <appType>
|
|
447
|
+
| `openyida integration create <appType> ... [--spec file.json]` | Create integration automation flow |
|
|
394
448
|
| `openyida integration list <appType> [--form-uuid <uuid>] [--status y\|n] [--json]` | List integration automation flows |
|
|
395
449
|
| `openyida integration enable <appType> <formUuid> <processCode>` | Enable integration automation flow |
|
|
396
450
|
| `openyida integration disable <appType> <formUuid> <processCode>` | Disable integration automation flow |
|
package/bin/yida.js
CHANGED
|
@@ -214,6 +214,16 @@ function handleFirstRunGuide() {
|
|
|
214
214
|
function printLoginResult(result) {
|
|
215
215
|
noteLoginCommandResult(result);
|
|
216
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
|
+
|
|
217
227
|
if (result && (result.status === 'need_qr_scan' || result.status === 'need_corp_selection')) {
|
|
218
228
|
console.log(JSON.stringify(result));
|
|
219
229
|
return;
|
|
@@ -245,13 +255,18 @@ function printLoginResult(result) {
|
|
|
245
255
|
return;
|
|
246
256
|
}
|
|
247
257
|
|
|
258
|
+
if (result.status && result.status !== 'ok' && !result.csrf_token) {
|
|
259
|
+
console.log(JSON.stringify(result));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
248
263
|
const summary = {
|
|
249
264
|
ok: true,
|
|
250
265
|
base_url: result && result.base_url,
|
|
251
266
|
corp_id: result && result.corp_id,
|
|
252
267
|
user_id: result && result.user_id,
|
|
253
268
|
csrf_token: result && result.csrf_token ? `${result.csrf_token.slice(0, 16)}...` : undefined,
|
|
254
|
-
cookies_count: Array.isArray(result && result.cookies) ? result.cookies.length : 0,
|
|
269
|
+
cookies_count: Array.isArray(result && result.cookies) ? result.cookies.length : (result.cookies_count || 0),
|
|
255
270
|
};
|
|
256
271
|
console.log(JSON.stringify(summary));
|
|
257
272
|
}
|
|
@@ -313,9 +328,11 @@ function shouldUsePlaywrightFallbackInAgentLogin() {
|
|
|
313
328
|
return hasDesktopEnvironment() || process.env.OPENYIDA_AGENT_PLAYWRIGHT_FALLBACK === '1';
|
|
314
329
|
}
|
|
315
330
|
|
|
316
|
-
function
|
|
317
|
-
const {
|
|
318
|
-
return
|
|
331
|
+
function shouldUseLocalBrowserLogin(options = {}) {
|
|
332
|
+
const { hasLocalBrowserLoginCapability } = require('../lib/auth/login');
|
|
333
|
+
return hasLocalBrowserLoginCapability({
|
|
334
|
+
playwrightFallback: options.playwrightFallback,
|
|
335
|
+
});
|
|
319
336
|
}
|
|
320
337
|
|
|
321
338
|
function shouldUseCodexQrLogin(cliArgs) {
|
|
@@ -542,6 +559,7 @@ async function main() {
|
|
|
542
559
|
case 'login': {
|
|
543
560
|
const { checkLoginOnly } = require('../lib/auth/login');
|
|
544
561
|
const loginArgs = applyLoginEnvironmentFlags(args, { inferTargetUrl: true });
|
|
562
|
+
const { isEnvAuthMode } = require('../lib/core/utils');
|
|
545
563
|
if (loginArgs.includes('--agent-poll') || loginArgs.includes('--codex-poll')) {
|
|
546
564
|
const sessionFile = getArgValue(loginArgs, '--agent-poll') || getArgValue(loginArgs, '--codex-poll');
|
|
547
565
|
const { pollCodexQrLogin } = require('../lib/auth/qr-login');
|
|
@@ -556,9 +574,12 @@ async function main() {
|
|
|
556
574
|
corpId: getArgValue(loginArgs, '--corp-id'),
|
|
557
575
|
});
|
|
558
576
|
printLoginResult(result);
|
|
559
|
-
} else if (loginArgs
|
|
577
|
+
} else if (loginArgs.includes('--check-only')) {
|
|
560
578
|
const result = checkLoginOnly({ includeSecrets: loginArgs.includes('--with-cookies') });
|
|
561
579
|
console.log(JSON.stringify(result, null, 2));
|
|
580
|
+
} else if (isEnvAuthMode()) {
|
|
581
|
+
const result = checkLoginOnly({ includeSecrets: true });
|
|
582
|
+
printLoginResult(result);
|
|
562
583
|
} else if (shouldUseCodexQrLogin(loginArgs)) {
|
|
563
584
|
const { startCodexQrLogin } = require('../lib/auth/qr-login');
|
|
564
585
|
const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
|
|
@@ -580,26 +601,17 @@ async function main() {
|
|
|
580
601
|
if (cachedResult.status === 'ok') {
|
|
581
602
|
printLoginResult(cachedResult);
|
|
582
603
|
} else {
|
|
583
|
-
const { detectActiveTool } = require('../lib/core/utils');
|
|
584
|
-
const activeTool = detectActiveTool();
|
|
585
604
|
const { interactiveLogin } = require('../lib/auth/login');
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
605
|
+
const playwrightFallback = shouldUsePlaywrightFallbackInAgentLogin();
|
|
606
|
+
const browserResult = shouldUseLocalBrowserLogin({ playwrightFallback })
|
|
607
|
+
? interactiveLogin({ playwrightFallback })
|
|
608
|
+
: null;
|
|
589
609
|
if (browserResult) {
|
|
590
610
|
printLoginResult(browserResult);
|
|
591
611
|
} else {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
const { codexLogin } = require('../lib/auth/codex-login');
|
|
596
|
-
const result = await codexLogin({ tool: activeTool.tool });
|
|
597
|
-
printLoginResult(result);
|
|
598
|
-
} else {
|
|
599
|
-
const { startCodexQrLogin } = require('../lib/auth/qr-login');
|
|
600
|
-
const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
|
|
601
|
-
printLoginResult(result);
|
|
602
|
-
}
|
|
612
|
+
const { startCodexQrLogin } = require('../lib/auth/qr-login');
|
|
613
|
+
const result = await startCodexQrLogin({ corpId: getArgValue(loginArgs, '--corp-id') });
|
|
614
|
+
printLoginResult(result);
|
|
603
615
|
}
|
|
604
616
|
}
|
|
605
617
|
} else if (shouldUseBrowserHandoffLogin(loginArgs)) {
|
|
@@ -617,7 +629,7 @@ async function main() {
|
|
|
617
629
|
printLoginResult(cachedResult);
|
|
618
630
|
break;
|
|
619
631
|
}
|
|
620
|
-
if (
|
|
632
|
+
if (shouldUseLocalBrowserLogin({ playwrightFallback: true })) {
|
|
621
633
|
const { interactiveLogin } = require('../lib/auth/login');
|
|
622
634
|
const browserResult = interactiveLogin({ playwrightFallback: true });
|
|
623
635
|
if (browserResult) {
|
|
@@ -760,6 +772,12 @@ async function main() {
|
|
|
760
772
|
break;
|
|
761
773
|
}
|
|
762
774
|
|
|
775
|
+
case 'er': {
|
|
776
|
+
const { run } = require('../lib/app/er');
|
|
777
|
+
await run(args);
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
|
|
763
781
|
case 'formula': {
|
|
764
782
|
const subCommand = args[0];
|
|
765
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
|
|