openyida 2026.9.7 → 2026.9.8-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 CHANGED
@@ -174,6 +174,8 @@ openyida update-app APP_XXX --theme-file .cache/openyida/crm/app-theme.css --nav
174
174
  openyida corp-efficiency
175
175
  openyida create-form create APP_XXX "Customer" .cache/openyida/forms/customer-fields.json
176
176
  openyida create-form update APP_XXX FORM_XXX .cache/openyida/forms/customer-changes.json
177
+ openyida create-form update APP_XXX FORM_XXX --data-file .cache/openyida/forms/customer-changes.json
178
+ openyida create-form resume APP_XXX FORM_XXX .cache/openyida/forms/customer-fields.json --json
177
179
  openyida sample openyida-page-template form-fields --output .cache/openyida/forms/customer-fields.json
178
180
  openyida sample openyida-page-template canvas-form-drawer --output project/pages/src/customer-entry.canvas.jsx --var APP_TYPE=APP_XXX --var FORM_UUID=FORM_XXX
179
181
  openyida get-schema APP_XXX FORM_XXX
@@ -413,7 +415,8 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
413
415
  | `openyida create-form create <appType> "<formTitle>" <fieldsJsonFile> [--icon auto\|<iconName>] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a form page |
414
416
  | `openyida create-form icons [--json]` | List available form navigation icons |
415
417
  | `openyida create-form validate-fields <fieldsJsonOrFile> [--json]` | Validate form field JSON locally |
416
- | `openyida create-form update <appType> ... [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Update a form page |
418
+ | `openyida create-form update <appType> <formUuid> (<changesJsonOrFile> \| --data-file <changesJsonOrFile>) [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Update a form page |
419
+ | `openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> [--json]` | Update a form page |
417
420
  | `openyida create-form patch <appType> <formUuid> <patchJsonOrFile> [--open\|--no-open]` | Update a form page |
418
421
  | `openyida create-form rule <appType> <formUuid> <rulesJsonOrFile> [--open\|--no-open]` | Update a form page |
419
422
  | `openyida create-form validation <appType> <formUuid> <validationsJsonOrFile> [--open\|--no-open]` | Update a form page |
@@ -89,6 +89,7 @@ function createParseArgs(dependencies) {
89
89
  contentLocale: null,
90
90
  browserOpenMode: openOption.mode,
91
91
  };
92
+ let dataFileInput;
92
93
 
93
94
  const args = [...rawArgs];
94
95
 
@@ -111,6 +112,14 @@ function createParseArgs(dependencies) {
111
112
  i--;
112
113
  } else if (args[i] === '--icon') {
113
114
  throwCreateFormError('--icon requires a value', 'CREATE_FORM_INVALID_ARGUMENTS');
115
+ } else if (args[i] === '--data-file') {
116
+ const next = args[i + 1];
117
+ if (dataFileInput !== undefined || !next || next.startsWith('--')) {
118
+ throwCreateFormError('--data-file requires exactly one value', 'CREATE_FORM_INVALID_ARGUMENTS');
119
+ }
120
+ dataFileInput = next;
121
+ args.splice(i, 2);
122
+ i--;
114
123
  } else if ((args[i] === '--locale' || args[i] === '--content-locale' || args[i] === '--lang') && i + 1 < args.length) {
115
124
  options.contentLocale = args[i + 1];
116
125
  if (!normalizeYidaLocale(options.contentLocale)) {
@@ -145,6 +154,10 @@ function createParseArgs(dependencies) {
145
154
 
146
155
  const mode = args[0];
147
156
 
157
+ if (dataFileInput !== undefined && mode !== 'update') {
158
+ throwCreateFormError('--data-file is only supported by create-form update', 'CREATE_FORM_INVALID_ARGUMENTS');
159
+ }
160
+
148
161
  if (mode === 'icons' || mode === 'list-icons') {
149
162
  return {
150
163
  mode: 'icons',
@@ -182,7 +195,12 @@ function createParseArgs(dependencies) {
182
195
  }
183
196
 
184
197
  if (mode === 'update') {
185
- if (args.length < 4) {
198
+ const positionalInput = args[3];
199
+ if (args.length > 4 || (positionalInput && dataFileInput !== undefined)) {
200
+ throwCreateFormError('Use either <changesJsonOrFile> or --data-file, not both', 'CREATE_FORM_INVALID_ARGUMENTS');
201
+ }
202
+ const changesJsonOrFile = dataFileInput !== undefined ? dataFileInput : positionalInput;
203
+ if (args.length < 3 || !changesJsonOrFile) {
186
204
  usage(t('create_form.usage_update'), t('create_form.example_update'));
187
205
  throwCreateFormError(t('create_form.usage_update'), 'CREATE_FORM_INVALID_ARGUMENTS');
188
206
  }
@@ -190,7 +208,23 @@ function createParseArgs(dependencies) {
190
208
  mode: 'update',
191
209
  appType: args[1],
192
210
  formUuid: args[2],
193
- changesJsonOrFile: args[3],
211
+ changesJsonOrFile,
212
+ ...options
213
+ };
214
+ }
215
+
216
+ if (mode === 'resume') {
217
+ if (args.length !== 4) {
218
+ throwCreateFormError(
219
+ 'openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json',
220
+ 'CREATE_FORM_INVALID_ARGUMENTS'
221
+ );
222
+ }
223
+ return {
224
+ mode: 'resume',
225
+ appType: args[1],
226
+ formUuid: args[2],
227
+ fieldsJsonOrFile: args[3],
194
228
  ...options
195
229
  };
196
230
  }
@@ -101,7 +101,10 @@ function execute(args) {
101
101
  }
102
102
 
103
103
  async function schedule(forms, concurrency, results, worker, save) {
104
- const pending = new Set(forms.filter(form => !results[form.key] || results[form.key].status === 'blocked').map(form => form.key));
104
+ const pending = new Set(forms.filter(form => {
105
+ const result = results[form.key];
106
+ return !result || result.status === 'blocked' || (result.status === 'failed' && result.formUuid);
107
+ }).map(form => form.key));
105
108
  const active = new Map();
106
109
  try {
107
110
  while (pending.size || active.size) {
@@ -114,7 +117,7 @@ async function schedule(forms, concurrency, results, worker, save) {
114
117
  }
115
118
  if (active.size >= concurrency || deps.some(status => status !== 'success')) { continue; }
116
119
  pending.delete(form.key);
117
- results[form.key] = { status: 'running' };
120
+ results[form.key] = { ...results[form.key], status: 'running' };
118
121
  save(); // Record intent before the request; an interrupted create is never retried automatically.
119
122
  const task = Promise.resolve().then(() => worker(form)).then(output => {
120
123
  results[form.key] = { ...output, status: 'success' };
@@ -178,16 +181,30 @@ async function run(args, dependencies = {}) {
178
181
  return matches[0].fieldId;
179
182
  };
180
183
  await schedule(forms, options.concurrency, state.results, async form => {
181
- let formUuid = form.formUuid;
184
+ let formUuid = form.formUuid || state.results[form.key]?.formUuid;
185
+ let shouldResume = Boolean(!form.formUuid && formUuid);
186
+ const resolvedFields = mapReferences(form.fields, resolve);
182
187
  if (!formUuid) {
183
- const argv = ['create-form', 'create', options.appType, form.title, JSON.stringify(mapReferences(form.fields, resolve)), '--no-open'];
188
+ const argv = ['create-form', 'create', options.appType, form.title, JSON.stringify(resolvedFields), '--no-open'];
184
189
  for (const key of ['icon', 'locale']) { if (form[key]) { argv.push(`--${key}`, form[key]); } }
185
- const created = await call(argv);
186
- if (typeof created.formUuid !== 'string' || !created.formUuid.startsWith('FORM')) { invalid(`create result: ${form.key}`); }
187
- formUuid = created.formUuid;
190
+ try {
191
+ const created = await call(argv);
192
+ if (typeof created.formUuid !== 'string' || !created.formUuid.startsWith('FORM')) { invalid(`create result: ${form.key}`); }
193
+ formUuid = created.formUuid;
194
+ } catch (error) {
195
+ const createdFormUuid = error.output?.formUuid || error.output?.details?.formUuid;
196
+ if (typeof createdFormUuid !== 'string' || !createdFormUuid.startsWith('FORM')) {
197
+ throw error;
198
+ }
199
+ formUuid = createdFormUuid;
200
+ shouldResume = true;
201
+ }
188
202
  }
189
203
  state.results[form.key].formUuid = formUuid;
190
204
  save(state);
205
+ if (shouldResume) {
206
+ await call(['create-form', 'resume', options.appType, formUuid, JSON.stringify(resolvedFields), '--json']);
207
+ }
191
208
  const schema = await call(['get-schema', options.appType, formUuid, '--field-map-json']);
192
209
  if (schema.formUuid !== formUuid || !Array.isArray(schema.fields)) { invalid(`schema: ${form.key}`); }
193
210
  return { formUuid, fields: schema.fields };
@@ -6,6 +6,8 @@ function dispatchCreateFormCommand(parsedArgs, authContext, handlers) {
6
6
  switch (parsedArgs.mode) {
7
7
  case 'update':
8
8
  return handlers.update(...args);
9
+ case 'resume':
10
+ return handlers.resume(...args);
9
11
  case 'patch':
10
12
  return handlers.patch(...args);
11
13
  case 'rule':
@@ -5911,6 +5911,297 @@ async function mainValidation(parsedArgs, authRef) {
5911
5911
 
5912
5912
  // ── update 模式主流程 ─────────────────────────────────
5913
5913
 
5914
+ function collectResumeFieldEvidence(fields, output) {
5915
+ const evidence = output || [];
5916
+ (fields || []).forEach(function (field) {
5917
+ if (!field || typeof field !== 'object') {
5918
+ return;
5919
+ }
5920
+ const labelText = extractLabelText(field);
5921
+ if (labelText && !isFormPresentationComponent(field.componentName)) {
5922
+ evidence.push({
5923
+ label: labelText,
5924
+ componentName: field.componentName,
5925
+ fieldId: field.props && field.props.fieldId ? field.props.fieldId : null,
5926
+ });
5927
+ }
5928
+ if (Array.isArray(field.children)) {
5929
+ collectResumeFieldEvidence(field.children.flat(), evidence);
5930
+ }
5931
+ });
5932
+ return evidence;
5933
+ }
5934
+
5935
+ function desiredResumeFieldIdentity(field) {
5936
+ const labelValue = field && field.label;
5937
+ const label = typeof labelValue === 'string'
5938
+ ? labelValue
5939
+ : labelValue && (labelValue.zh_CN || labelValue.ja_JP || labelValue.en_US || labelValue.pureEn_US);
5940
+ return {
5941
+ label: String(label || '').trim(),
5942
+ componentName: normalizeFormDefinitionType(field),
5943
+ };
5944
+ }
5945
+
5946
+ function collectResumeDesiredFields(fields, options) {
5947
+ const output = [];
5948
+ const verifyNestedFields = Boolean(options && options.verifyNestedFields);
5949
+
5950
+ function visit(value) {
5951
+ if (Array.isArray(value)) {
5952
+ value.forEach(visit);
5953
+ return;
5954
+ }
5955
+ if (!value || typeof value !== 'object') {
5956
+ return;
5957
+ }
5958
+ const componentName = normalizeFormDefinitionType(value);
5959
+ if (isSupportedBusinessFieldType(componentName)) {
5960
+ output.push(value);
5961
+ if (!verifyNestedFields) {
5962
+ return;
5963
+ }
5964
+ }
5965
+ if (Array.isArray(value.children)) {
5966
+ value.children.forEach(visit);
5967
+ }
5968
+ }
5969
+
5970
+ visit(fields);
5971
+ return output;
5972
+ }
5973
+
5974
+ function isRecoverableBlankResumeSchema(schema) {
5975
+ const allowedShellComponents = new Set(['Page', 'RootHeader', 'RootContent', 'RootFooter', 'FooterYida']);
5976
+ const componentsTree = schema && schema.pages && schema.pages[0] && schema.pages[0].componentsTree;
5977
+ if (!Array.isArray(componentsTree) || componentsTree.length === 0) {
5978
+ return true;
5979
+ }
5980
+ let safe = true;
5981
+ function visit(node) {
5982
+ if (!node || typeof node !== 'object' || !safe) {
5983
+ return;
5984
+ }
5985
+ if (node.componentName && !allowedShellComponents.has(node.componentName)) {
5986
+ safe = false;
5987
+ return;
5988
+ }
5989
+ if (Array.isArray(node.children)) {
5990
+ node.children.forEach(visit);
5991
+ }
5992
+ }
5993
+ componentsTree.forEach(visit);
5994
+ return safe;
5995
+ }
5996
+
5997
+ function buildResumeChanges(existingFields, desiredFields) {
5998
+ const existingByLabel = new Map();
5999
+ existingFields.forEach(function (field) {
6000
+ const bucket = existingByLabel.get(field.label) || [];
6001
+ bucket.push(field);
6002
+ existingByLabel.set(field.label, bucket);
6003
+ });
6004
+
6005
+ const desiredLabels = new Set();
6006
+ const missing = [];
6007
+ const existing = [];
6008
+ const conflicts = [];
6009
+ desiredFields.forEach(function (field) {
6010
+ const identity = desiredResumeFieldIdentity(field);
6011
+ if (!identity.label || desiredLabels.has(identity.label)) {
6012
+ conflicts.push({
6013
+ code: identity.label ? 'CREATE_FORM_RESUME_DUPLICATE_DESIRED_FIELD' : 'CREATE_FORM_RESUME_FIELD_LABEL_REQUIRED',
6014
+ label: identity.label || null,
6015
+ });
6016
+ return;
6017
+ }
6018
+ desiredLabels.add(identity.label);
6019
+ const matches = existingByLabel.get(identity.label) || [];
6020
+ if (matches.length === 0) {
6021
+ missing.push(field);
6022
+ return;
6023
+ }
6024
+ if (matches.length !== 1 || matches[0].componentName !== identity.componentName) {
6025
+ conflicts.push({
6026
+ code: 'CREATE_FORM_RESUME_FIELD_CONFLICT',
6027
+ label: identity.label,
6028
+ requestedType: identity.componentName,
6029
+ observedTypes: matches.map(function (item) { return item.componentName; }),
6030
+ });
6031
+ return;
6032
+ }
6033
+ existing.push({
6034
+ label: identity.label,
6035
+ componentName: identity.componentName,
6036
+ fieldId: matches[0].fieldId,
6037
+ });
6038
+ });
6039
+ return { missing, existing, conflicts };
6040
+ }
6041
+
6042
+ async function readResumeSchema(authRef, appType, formUuid) {
6043
+ const schemaResult = await requestWithAutoLogin(function (auth) {
6044
+ return sendGetRequest(
6045
+ auth.baseUrl,
6046
+ buildApiPath(appType, 'getFormSchema', { prefix: '_view', namespace: 'alibaba' }),
6047
+ { formUuid: formUuid, schemaVersion: 'V5' }
6048
+ );
6049
+ }, authRef);
6050
+ if (!schemaResult || schemaResult.success === false || schemaResult.__needLogin || schemaResult.__csrfExpired) {
6051
+ throwCreateFormError(t('create_form.resume_readback_failed'), 'CREATE_FORM_RESUME_READBACK_FAILED', {
6052
+ appType,
6053
+ formUuid,
6054
+ result: sanitizeFailureResult(schemaResult),
6055
+ });
6056
+ }
6057
+ if (schemaResult.appType && schemaResult.appType !== appType) {
6058
+ throwCreateFormError(t('create_form.resume_ownership_unverified'), 'CREATE_FORM_RESUME_OWNERSHIP_UNVERIFIED', {
6059
+ appType,
6060
+ formUuid,
6061
+ });
6062
+ }
6063
+ if (schemaResult.formUuid && schemaResult.formUuid !== formUuid) {
6064
+ throwCreateFormError(t('create_form.resume_identity_mismatch'), 'CREATE_FORM_RESUME_OWNERSHIP_UNVERIFIED', {
6065
+ appType,
6066
+ formUuid,
6067
+ });
6068
+ }
6069
+ const schema = schemaResult.content
6070
+ ? (typeof schemaResult.content === 'string' ? JSON.parse(schemaResult.content) : schemaResult.content)
6071
+ : schemaResult.pages ? schemaResult : null;
6072
+ if (!schema || !Array.isArray(schema.pages) || schema.pages.length === 0) {
6073
+ throwCreateFormError(t('create_form.resume_schema_invalid'), 'CREATE_FORM_RESUME_SCHEMA_INVALID', {
6074
+ appType,
6075
+ formUuid,
6076
+ });
6077
+ }
6078
+ return { schemaResult, schema, version: extractSchemaServerRevision(schemaResult) };
6079
+ }
6080
+
6081
+ async function mainResume(parsedArgs, authRef) {
6082
+ const { appType, formUuid, fieldsJsonOrFile } = parsedArgs;
6083
+ assertNoEmojiInDefinitionFileName(fieldsJsonOrFile);
6084
+ const { fields, validations } = readFieldsDefinition(fieldsJsonOrFile);
6085
+ assertNoEmojiInFormDefinition(formUuid, fields, [], 'create-form resume input');
6086
+ validateFormFieldDefinitions(fields);
6087
+
6088
+ const firstRead = await readResumeSchema(authRef, appType, formUuid);
6089
+ const root = firstRead.schema.pages[0].componentsTree && firstRead.schema.pages[0].componentsTree[0];
6090
+ const formContainer = root ? findFormContainer(root) : null;
6091
+ const completedStages = ['read_target', 'verify_ownership'];
6092
+ let recoveredBlankShell = false;
6093
+ let plan;
6094
+
6095
+ if (!formContainer) {
6096
+ if (!isRecoverableBlankResumeSchema(firstRead.schema)) {
6097
+ throwCreateFormError(t('create_form.resume_container_invalid'), 'CREATE_FORM_RESUME_SCHEMA_INVALID', {
6098
+ appType,
6099
+ formUuid,
6100
+ retryable: false,
6101
+ remoteWrites: 0,
6102
+ });
6103
+ }
6104
+ const corpId = resolveCorpId(authRef.authData);
6105
+ const formTitle = firstRead.schemaResult.formTitle || firstRead.schemaResult.title || formUuid;
6106
+ firstRead.schema = buildFormSchema(formTitle, fields, formUuid, corpId, appType, 'single', 'default', 'top');
6107
+ const resumeValidationRules = collectSmartValidationRulesFromFields(fields).concat(validations || []);
6108
+ if (resumeValidationRules.length > 0) {
6109
+ applySmartValidations(firstRead.schema, resumeValidationRules);
6110
+ }
6111
+ await saveFormSchema(authRef, appType, formUuid, firstRead.schema, firstRead.version, 4);
6112
+ completedStages.push('rebuild_blank_schema', 'save_schema');
6113
+ recoveredBlankShell = true;
6114
+ plan = {
6115
+ existing: [],
6116
+ missing: collectResumeDesiredFields(fields, { verifyNestedFields: true }),
6117
+ conflicts: [],
6118
+ };
6119
+ } else if (!Array.isArray(formContainer.children)) {
6120
+ throwCreateFormError(t('create_form.resume_container_invalid'), 'CREATE_FORM_RESUME_SCHEMA_INVALID', {
6121
+ appType,
6122
+ formUuid,
6123
+ retryable: false,
6124
+ remoteWrites: 0,
6125
+ });
6126
+ } else {
6127
+ plan = buildResumeChanges(
6128
+ collectResumeFieldEvidence(formContainer.children),
6129
+ collectResumeDesiredFields(fields)
6130
+ );
6131
+ if (plan.conflicts.length > 0) {
6132
+ throwCreateFormError(t('create_form.resume_field_conflict'), 'CREATE_FORM_RESUME_CONFLICT', {
6133
+ appType,
6134
+ formUuid,
6135
+ retryable: false,
6136
+ remoteWrites: 0,
6137
+ diagnostics: plan.conflicts,
6138
+ });
6139
+ }
6140
+ completedStages.push('compare_fields');
6141
+ }
6142
+
6143
+ if (!recoveredBlankShell && plan.missing.length > 0) {
6144
+ const applied = applyChangesToSchema(
6145
+ firstRead.schema,
6146
+ plan.missing.map(function (field) { return { action: 'add', field }; }),
6147
+ { verbose: true }
6148
+ );
6149
+ if ((applied.diagnostics || []).length > 0) {
6150
+ throwCreateFormError(t('create_form.resume_field_resolution_failed'), 'CREATE_FORM_RESUME_CONFLICT', {
6151
+ appType,
6152
+ formUuid,
6153
+ retryable: false,
6154
+ remoteWrites: 0,
6155
+ diagnostics: applied.diagnostics,
6156
+ });
6157
+ }
6158
+ const corpId = resolveCorpId(authRef.authData);
6159
+ const updatedContainer = findFormContainer(firstRead.schema.pages[0].componentsTree[0]);
6160
+ fillSerialNumberFormulas(updatedContainer.children, corpId, appType, formUuid);
6161
+ await saveFormSchema(authRef, appType, formUuid, firstRead.schema, firstRead.version, 4);
6162
+ completedStages.push('add_missing_fields', 'save_schema');
6163
+ }
6164
+
6165
+ const finalRead = await readResumeSchema(authRef, appType, formUuid);
6166
+ const finalContainer = findFormContainer(finalRead.schema.pages[0].componentsTree[0]);
6167
+ const finalPlan = buildResumeChanges(
6168
+ collectResumeFieldEvidence(finalContainer && finalContainer.children),
6169
+ collectResumeDesiredFields(fields, { verifyNestedFields: true })
6170
+ );
6171
+ if (finalPlan.missing.length > 0 || finalPlan.conflicts.length > 0) {
6172
+ throwCreateFormError(t('create_form.resume_readback_mismatch'), 'CREATE_FORM_RESUME_READBACK_MISMATCH', {
6173
+ appType,
6174
+ formUuid,
6175
+ retryable: false,
6176
+ resultUnknown: true,
6177
+ completedStages,
6178
+ missingFieldCount: finalPlan.missing.length,
6179
+ diagnostics: finalPlan.conflicts,
6180
+ });
6181
+ }
6182
+ completedStages.push('verify_final_schema');
6183
+ const formUrl = authRef.baseUrl + '/' + appType + '/workbench/' + formUuid;
6184
+ const output = {
6185
+ success: true,
6186
+ appType,
6187
+ formUuid,
6188
+ completedStages,
6189
+ requestedFieldCount: fields.length,
6190
+ existingFieldCount: plan.existing.length,
6191
+ addedFieldCount: plan.missing.length,
6192
+ finalFieldCount: collectResumeFieldEvidence(finalContainer.children).length,
6193
+ recoveredBlankShell,
6194
+ url: formUrl,
6195
+ };
6196
+ console.log(JSON.stringify(withBrowserHandoff(
6197
+ output,
6198
+ formUrl,
6199
+ { stage: 'resume_form_success', title: formUuid },
6200
+ parsedArgs.browserOpenMode
6201
+ )));
6202
+ return output;
6203
+ }
6204
+
5914
6205
  async function mainUpdate(parsedArgs, authRef) {
5915
6206
  const { appType, formUuid, changesJsonOrFile } = parsedArgs;
5916
6207
 
@@ -6102,6 +6393,7 @@ async function run(args) {
6102
6393
  {
6103
6394
  create: mainCreate,
6104
6395
  update: mainUpdate,
6396
+ resume: mainResume,
6105
6397
  patch: mainPatch,
6106
6398
  rule: mainRule,
6107
6399
  validation: mainValidation,
@@ -449,6 +449,7 @@ const COMMAND_SIDE_EFFECTS = new Map([
449
449
  'create-form.bind-datasource',
450
450
  'create-form.create',
451
451
  'create-form.patch',
452
+ 'create-form.resume',
452
453
  'create-form.rule',
453
454
  'create-form.update',
454
455
  'create-form.validation',
@@ -689,6 +690,7 @@ const COMMAND_PERMISSIONS = new Map([
689
690
  'create-form.create',
690
691
  'create-form.batch',
691
692
  'create-form.patch',
693
+ 'create-form.resume',
692
694
  'create-form.rule',
693
695
  'create-form.update',
694
696
  'create-form.validation',
@@ -1223,7 +1225,8 @@ const COMMAND_GROUPS = [
1223
1225
  command('create-form.validate-fields', ['create-form', 'validate-fields'], 'create-form validate-fields <fieldsJsonOrFile> [--json]', 'help.cmd_validate_form', {
1224
1226
  requiresLogin: false,
1225
1227
  }),
1226
- command('create-form.update', ['create-form', 'update'], 'create-form update <appType> ... [--locale zh_CN|en_US|ja_JP] [--open|--no-open]', 'help.cmd_update_form'),
1228
+ command('create-form.update', ['create-form', 'update'], 'create-form update <appType> <formUuid> (<changesJsonOrFile> | --data-file <changesJsonOrFile>) [--locale zh_CN|en_US|ja_JP] [--open|--no-open]', 'help.cmd_update_form'),
1229
+ command('create-form.resume', ['create-form', 'resume'], 'create-form resume <appType> <formUuid> <fieldsJsonOrFile> [--json]', 'help.cmd_update_form'),
1227
1230
  command('create-form.patch', ['create-form', 'patch'], 'create-form patch <appType> <formUuid> <patchJsonOrFile> [--open|--no-open]', 'help.cmd_update_form'),
1228
1231
  command('create-form.rule', ['create-form', 'rule'], 'create-form rule <appType> <formUuid> <rulesJsonOrFile> [--open|--no-open]', 'help.cmd_update_form'),
1229
1232
  command('create-form.validation', ['create-form', 'validation'], 'create-form validation <appType> <formUuid> <validationsJsonOrFile> [--open|--no-open]', 'help.cmd_update_form'),
@@ -414,9 +414,9 @@ Examples:
414
414
  create_opt_spec: ' --spec <file.json> Use a structured flow spec for complex automation nodes (dataUpdate/route, etc.)',
415
415
  create_opt_data_form_uuid: ' --data-form-uuid <uuid> Target form UUID for a get-single-data node',
416
416
  create_opt_data_condition: ' --data-condition <rule> Get-data condition: targetField:label:triggerField[:component[:opCode[:valueType]]]',
417
- create_opt_get_self: ' --get-self Insert a get-self node (pid equals trigger form instance ID)',
417
+ create_opt_get_self: ' --get-self Insert a get-self node (process runtime uses pid, designer uses proc_inst_id; ordinary forms use form_inst_id on both sides)',
418
418
  create_opt_get_self_field: ' --get-self-field <field> Override the trigger-side system field, default __masterdata_form_inst_id',
419
- create_opt_get_self_query_field: ' --get-self-query-field <f> Override the query-side system field, default pid',
419
+ create_opt_get_self_query_field: ' --get-self-query-field <f> Override the query-side system field (process: pid runtime / proc_inst_id designer; ordinary: form_inst_id)',
420
420
  create_opt_add_data_form_uuid: ' --add-data-form-uuid <uuid> Target form UUID for an add-data node',
421
421
  create_opt_add_data_assignment: ' --add-data-assignment <rule> Add-data assignment: targetField:valueType:value',
422
422
  create_opt_initiate_approval_form_uuid: ' --initiate-approval-form-uuid <uuid> Target process-form UUID for an initiate-approval node',
@@ -432,6 +432,11 @@ Examples:
432
432
  create_example2: ' openyida integration create APP_XXX FORM-XXX "Get self then notify" --get-self --publish',
433
433
  create_missing_args: 'Missing required arguments.',
434
434
  create_replace_required: 'Using --process-code fully replaces the existing flow. Pass --replace explicitly. Safe editing is not currently available; integration update only reports capability status.',
435
+ create_source_form_fetch_failed: 'Could not read the data-source form metadata; remote write stopped: {0}',
436
+ create_source_form_not_found: 'Could not find data-source form {0} in navigation; remote write stopped.',
437
+ create_source_form_type_unknown: 'Navigation did not return a verifiable data-source form type; remote write stopped.',
438
+ create_source_form_type_invalid: 'Navigation returned unsupported data-source form type "{0}"; remote write stopped.',
439
+ create_source_form_type_mismatch: 'Explicit formType={0} conflicts with navigation metadata {1}; remote write stopped.',
435
440
  create_flow_name_too_long: 'Logic-flow names cannot exceed {0} characters (received {1}).',
436
441
  create_invalid_events: 'No valid trigger event was recognized.',
437
442
  create_no_receivers: 'No notification receiver or user field specified; no message node will be generated.',
@@ -449,7 +454,7 @@ Examples:
449
454
  create_notify_content: 'Notification content: {0}',
450
455
  create_data_form: 'Get-data form: {0}',
451
456
  create_data_conditions: 'Get-data condition count: {0}',
452
- create_get_self_summary: 'Get-self guardrail: {0} equals field {1}',
457
+ create_get_self_summary: 'Get-self guardrail: runtime query field {0} equals field {1}; process-form designer maps it to proc_inst_id, while ordinary forms keep the same field',
453
458
  create_op_mode_publish: 'Mode: save and publish',
454
459
  create_op_mode_draft: 'Mode: save draft only',
455
460
  create_step: '[{0}/{1}] {2}',
@@ -822,7 +827,15 @@ Examples:
822
827
  example_update: 'Example: openyida create-form update "APP_XXX" "FORM-YYY" \'[{"action":"add","field":{"type":"TextField","label":"Note"}}]\'',
823
828
  usage_label: 'Usage:',
824
829
  usage_create_short: ' create: openyida create-form create <appType> <formTitle> <fieldsJsonFile>',
825
- usage_update_short: ' update: openyida create-form update <appType> <formUuid> <changesJsonOrFile>',
830
+ usage_update_short: ' update: openyida create-form update <appType> <formUuid> <changesJsonOrFile> or --data-file <changesJsonOrFile>',
831
+ resume_readback_failed: 'Unable to read the target form before resume.',
832
+ resume_ownership_unverified: 'The target form does not belong to the requested app; resume stopped.',
833
+ resume_identity_mismatch: 'The target form identity does not match the readback; resume stopped.',
834
+ resume_schema_invalid: 'The target form schema is unavailable.',
835
+ resume_container_invalid: 'The target form container is unavailable.',
836
+ resume_field_conflict: 'Existing fields conflict with the requested definition; resume stopped.',
837
+ resume_field_resolution_failed: 'Resume field resolution failed.',
838
+ resume_readback_mismatch: 'Resume readback did not confirm all requested fields.',
826
839
  example_label: '\nExamples:',
827
840
  fields_file_not_found: ' ❌ Fields definition file not found: ',
828
841
  fields_format_invalid: 'Invalid fields definition format',
@@ -410,9 +410,9 @@ openyida - 宜搭命令行工具
410
410
  create_opt_spec: ' --spec <file.json> 使用结构化编排文件创建复杂自动化(dataUpdate/route 等)',
411
411
  create_opt_data_form_uuid: ' --data-form-uuid <uuid> 插入获取单条数据节点的目标表单 UUID',
412
412
  create_opt_data_condition: ' --data-condition <rule> 获取数据过滤条件:目标字段:字段名:触发字段[:组件[:操作符[:值类型]]]',
413
- create_opt_get_self: ' --get-self 自动插入获取自身节点(pid 等于触发事件表单实例ID)',
413
+ create_opt_get_self: ' --get-self 自动插入获取自身节点(流程表单运行态使用 pid、设计器使用 proc_inst_id;普通表单两侧使用 form_inst_id)',
414
414
  create_opt_get_self_field: ' --get-self-field <field> 覆盖右侧触发事件系统字段,默认 __masterdata_form_inst_id',
415
- create_opt_get_self_query_field: ' --get-self-query-field <f> 覆盖左侧查询系统字段,默认 pid',
415
+ create_opt_get_self_query_field: ' --get-self-query-field <f> 覆盖左侧查询系统字段(流程表单默认 pid,普通表单默认 form_inst_id)',
416
416
  create_opt_add_data_form_uuid: ' --add-data-form-uuid <uuid> 插入新增数据节点的目标表单 UUID',
417
417
  create_opt_add_data_assignment: ' --add-data-assignment <rule> 新增数据赋值:目标字段:valueType:value',
418
418
  create_opt_initiate_approval_form_uuid: ' --initiate-approval-form-uuid <uuid> 发起审批节点的目标流程表单 UUID',
@@ -428,6 +428,11 @@ openyida - 宜搭命令行工具
428
428
  create_example2: ' openyida integration create APP_XXX FORM-XXX "获取自身后通知" --get-self --publish',
429
429
  create_missing_args: '缺少必要参数。',
430
430
  create_replace_required: '使用 --process-code 会整图替换已有逻辑流;必须显式传入 --replace。安全二次编辑当前不可用,integration update 仅报告 capability 状态。',
431
+ create_source_form_fetch_failed: '获取取数来源表单信息失败,已停止远端写入: {0}',
432
+ create_source_form_not_found: '获取取数来源表单信息失败,导航中未找到表单 {0},已停止远端写入',
433
+ create_source_form_type_unknown: '获取取数来源表单信息失败,导航未返回可确认的表单类型,已停止远端写入',
434
+ create_source_form_type_invalid: '获取取数来源表单信息失败,导航返回的表单类型“{0}”不是可取数表单,已停止远端写入',
435
+ create_source_form_type_mismatch: '获取取数来源表单信息失败,显式 formType={0} 与导航元数据 {1} 不一致,已停止远端写入',
431
436
  create_flow_name_too_long: '逻辑流名称不能超过 {0} 个字符(当前 {1} 个)。',
432
437
  create_invalid_events: '未识别到有效触发事件。',
433
438
  create_no_receivers: '未指定通知接收人或成员字段,将不会生成消息通知节点。',
@@ -445,7 +450,7 @@ openyida - 宜搭命令行工具
445
450
  create_notify_content: '通知内容: {0}',
446
451
  create_data_form: '获取数据表单: {0}',
447
452
  create_data_conditions: '获取数据条件数: {0}',
448
- create_get_self_summary: '获取自身闭坑: {0} 等于 字段 {1}',
453
+ create_get_self_summary: '获取自身闭坑: 运行态查询字段 {0} 等于字段 {1};流程表单设计器对应 proc_inst_id,普通表单设计器保持一致',
449
454
  create_op_mode_publish: '操作模式: 保存并发布',
450
455
  create_op_mode_draft: '操作模式: 仅保存草稿',
451
456
  create_step: '[{0}/{1}] {2}',
@@ -793,7 +798,15 @@ openyida - 宜搭命令行工具
793
798
  example_update: '示例:openyida create-form update "APP_XXX" "FORM-YYY" \'[{"action":"add","field":{"type":"TextField","label":"备注"}}]\'',
794
799
  usage_label: '用法:',
795
800
  usage_create_short: ' 创建: openyida create-form create <appType> <formTitle> <fieldsJsonFile>',
796
- usage_update_short: ' 更新: openyida create-form update <appType> <formUuid> <changesJsonOrFile>',
801
+ usage_update_short: ' 更新: openyida create-form update <appType> <formUuid> <changesJsonOrFile> 或 --data-file <changesJsonOrFile>',
802
+ resume_readback_failed: '恢复前无法回读目标表单。',
803
+ resume_ownership_unverified: '目标表单不属于指定应用,已停止恢复。',
804
+ resume_identity_mismatch: '目标表单身份与回读结果不一致,已停止恢复。',
805
+ resume_schema_invalid: '目标表单 Schema 不可用。',
806
+ resume_container_invalid: '目标表单容器不可用。',
807
+ resume_field_conflict: '已有字段与请求定义冲突,恢复已停止。',
808
+ resume_field_resolution_failed: '恢复字段解析失败。',
809
+ resume_readback_mismatch: '恢复后的回读未确认全部请求字段。',
797
810
  example_label: '\n示例:',
798
811
  fields_file_not_found: ' ❌ 字段定义文件不存在: ',
799
812
  fields_format_invalid: '字段定义格式不正确',