openxiangda 1.0.118 → 1.0.119
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/lib/cli.js +299 -1
- package/lib/workspace-init.js +1 -0
- package/openxiangda-skills/references/component-guide.md +8 -7
- package/openxiangda-skills/references/forms/component-registry.md +1 -0
- package/openxiangda-skills/references/platform-data-model.md +2 -2
- package/openxiangda-skills/references/resource-manifest-cheatsheet.md +39 -0
- package/package.json +1 -1
- package/packages/sdk/dist/{ProcessPreview-Cw7X8odD.d.mts → ProcessPreview-CFmuu427.d.mts} +13 -3
- package/packages/sdk/dist/{ProcessPreview-Cw7X8odD.d.ts → ProcessPreview-CFmuu427.d.ts} +13 -3
- package/packages/sdk/dist/components/index.cjs +134 -11
- package/packages/sdk/dist/components/index.cjs.map +1 -1
- package/packages/sdk/dist/components/index.d.mts +2 -2
- package/packages/sdk/dist/components/index.d.ts +2 -2
- package/packages/sdk/dist/components/index.mjs +134 -11
- package/packages/sdk/dist/components/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/index.cjs +134 -11
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +1 -1
- package/packages/sdk/dist/runtime/index.d.ts +1 -1
- package/packages/sdk/dist/runtime/index.mjs +134 -11
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.d.mts +1 -1
- package/packages/sdk/dist/runtime/react.d.ts +1 -1
- package/packages/sdk/src/build-source/scripts/utils/form-api.mjs +1 -0
package/lib/cli.js
CHANGED
|
@@ -1458,6 +1458,7 @@ async function workspace(args) {
|
|
|
1458
1458
|
roles: {},
|
|
1459
1459
|
connectors: {},
|
|
1460
1460
|
dataViews: {},
|
|
1461
|
+
storageConfigs: {},
|
|
1461
1462
|
pagePermissionGroups: {},
|
|
1462
1463
|
formPermissionGroups: {},
|
|
1463
1464
|
formSettings: {},
|
|
@@ -4909,6 +4910,7 @@ function ensureResourceBuckets(bound) {
|
|
|
4909
4910
|
bound.resources.roles = bound.resources.roles || {};
|
|
4910
4911
|
bound.resources.connectors = bound.resources.connectors || {};
|
|
4911
4912
|
bound.resources.dataViews = bound.resources.dataViews || {};
|
|
4913
|
+
bound.resources.storageConfigs = bound.resources.storageConfigs || {};
|
|
4912
4914
|
bound.resources.authConfigs = bound.resources.authConfigs || {};
|
|
4913
4915
|
bound.resources.routes = bound.resources.routes || {};
|
|
4914
4916
|
bound.resources.publicAccessPolicies = bound.resources.publicAccessPolicies || {};
|
|
@@ -5122,6 +5124,14 @@ function saveDataViewResource(target, dataViewCode, dataViewId, extra = {}) {
|
|
|
5122
5124
|
}, keys);
|
|
5123
5125
|
}
|
|
5124
5126
|
|
|
5127
|
+
function saveStorageConfigResource(target, storageCode, storageConfigId, extra = {}) {
|
|
5128
|
+
const keys = ['storageConfigId', 'provider', 'status'];
|
|
5129
|
+
saveStateResource(target, 'storageConfigs', storageCode, {
|
|
5130
|
+
...pickStateFields(extra, keys),
|
|
5131
|
+
storageConfigId,
|
|
5132
|
+
}, keys);
|
|
5133
|
+
}
|
|
5134
|
+
|
|
5125
5135
|
function saveRouteResource(target, routeCode, routeId, extra = {}) {
|
|
5126
5136
|
const keys = ['routeId', 'pathPattern', 'publicAccess', 'publicPolicyCode'];
|
|
5127
5137
|
saveStateResource(target, 'routes', routeCode, {
|
|
@@ -5253,6 +5263,7 @@ const RESOURCE_SPECS = [
|
|
|
5253
5263
|
{ key: 'automations', dir: 'automations', topFiles: ['automations.json'], pluralKeys: ['automations'] },
|
|
5254
5264
|
{ key: 'functions', dir: 'functions', topFiles: ['functions.json'], pluralKeys: ['functions'] },
|
|
5255
5265
|
{ key: 'dataViews', dir: 'data-views', topFiles: ['data-views.json'], pluralKeys: ['dataViews', 'data-views'] },
|
|
5266
|
+
{ key: 'storageConfigs', dir: 'storage', topFiles: ['storage.json'], pluralKeys: ['storageConfigs', 'storage'] },
|
|
5256
5267
|
{ key: 'authConfigs', dir: 'auth', topFiles: ['auth.json'], pluralKeys: ['authConfigs', 'auth'] },
|
|
5257
5268
|
{ key: 'routes', dir: 'routes', topFiles: ['routes.json'], pluralKeys: ['routes'] },
|
|
5258
5269
|
{
|
|
@@ -5305,6 +5316,15 @@ const RESOURCE_TYPE_ALIASES = new Map([
|
|
|
5305
5316
|
['dataview', 'dataViews'],
|
|
5306
5317
|
['dataviews', 'dataViews'],
|
|
5307
5318
|
['data-view-resource', 'dataViews'],
|
|
5319
|
+
['storage', 'storageConfigs'],
|
|
5320
|
+
['storages', 'storageConfigs'],
|
|
5321
|
+
['storage-config', 'storageConfigs'],
|
|
5322
|
+
['storage-configs', 'storageConfigs'],
|
|
5323
|
+
['storageconfig', 'storageConfigs'],
|
|
5324
|
+
['storageconfigs', 'storageConfigs'],
|
|
5325
|
+
['oss', 'storageConfigs'],
|
|
5326
|
+
['oss-config', 'storageConfigs'],
|
|
5327
|
+
['oss-configs', 'storageConfigs'],
|
|
5308
5328
|
['auth', 'authConfigs'],
|
|
5309
5329
|
['auth-config', 'authConfigs'],
|
|
5310
5330
|
['auth-configs', 'authConfigs'],
|
|
@@ -5369,7 +5389,7 @@ function getResourceTypeFilters(positional = [], flags = {}) {
|
|
|
5369
5389
|
if (!key) {
|
|
5370
5390
|
fail(
|
|
5371
5391
|
`未知资源类型: ${rawType}。常用类型包括 workflow, notification, route, menu, role, ` +
|
|
5372
|
-
`page-permission-group, form-permission-group, public-access。`
|
|
5392
|
+
`storage, page-permission-group, form-permission-group, public-access。`
|
|
5373
5393
|
);
|
|
5374
5394
|
}
|
|
5375
5395
|
filters.add(key);
|
|
@@ -5636,6 +5656,7 @@ function generateResourceTypes(manifest, outputFile) {
|
|
|
5636
5656
|
);
|
|
5637
5657
|
const dataViewCodes = unique((manifest.dataViews || []).map(item => item.code).filter(Boolean));
|
|
5638
5658
|
const functionCodes = unique((manifest.functions || []).map(item => item.code).filter(Boolean));
|
|
5659
|
+
const storageConfigCodes = unique((manifest.storageConfigs || []).map(item => item.code).filter(Boolean));
|
|
5639
5660
|
const authConfigCodes = unique((manifest.authConfigs || []).map(item => item.code).filter(Boolean));
|
|
5640
5661
|
const publicAccessPolicyCodes = unique((manifest.publicAccessPolicies || []).map(item => item.code).filter(Boolean));
|
|
5641
5662
|
const content = [
|
|
@@ -5654,6 +5675,9 @@ function generateResourceTypes(manifest, outputFile) {
|
|
|
5654
5675
|
`export const dataViewCodes = ${JSON.stringify(dataViewCodes, null, 2)} as const`,
|
|
5655
5676
|
'export type DataViewCode = typeof dataViewCodes[number]',
|
|
5656
5677
|
'',
|
|
5678
|
+
`export const storageConfigCodes = ${JSON.stringify(storageConfigCodes, null, 2)} as const`,
|
|
5679
|
+
'export type StorageConfigCode = typeof storageConfigCodes[number]',
|
|
5680
|
+
'',
|
|
5657
5681
|
`export const functionCodes = ${JSON.stringify(functionCodes, null, 2)} as const`,
|
|
5658
5682
|
'export type FunctionCode = typeof functionCodes[number]',
|
|
5659
5683
|
'',
|
|
@@ -5678,6 +5702,7 @@ function generateResourceTypes(manifest, outputFile) {
|
|
|
5678
5702
|
routeCodes: routeCodes.length,
|
|
5679
5703
|
pagePermissionGroups: pagePermissionGroupCodes.length,
|
|
5680
5704
|
dataViews: dataViewCodes.length,
|
|
5705
|
+
storageConfigs: storageConfigCodes.length,
|
|
5681
5706
|
functions: functionCodes.length,
|
|
5682
5707
|
authConfigs: authConfigCodes.length,
|
|
5683
5708
|
publicAccessPolicies: publicAccessPolicyCodes.length,
|
|
@@ -5759,6 +5784,27 @@ function validateResourceItem(kind, item, errors, warnings) {
|
|
|
5759
5784
|
}
|
|
5760
5785
|
validateDataViewPerformance(label, definition, errors, warnings, storageMode);
|
|
5761
5786
|
}
|
|
5787
|
+
if (kind === 'storageConfigs') {
|
|
5788
|
+
const config = item.configJson || item.config || item;
|
|
5789
|
+
const provider = String(item.provider || config.provider || 'oss').toLowerCase();
|
|
5790
|
+
if (provider !== 'oss') errors.push(`${label}: 当前仅支持 provider=oss`);
|
|
5791
|
+
if (!item.name && !config.name) warnings.push(`${label}: 未声明 name,将使用 code`);
|
|
5792
|
+
if (!config.region) errors.push(`${label}: 缺少 OSS region`);
|
|
5793
|
+
if (!config.bucket) errors.push(`${label}: 缺少 OSS bucket`);
|
|
5794
|
+
const status = item.status === undefined ? 'active' : String(item.status);
|
|
5795
|
+
if (!['active', 'disabled'].includes(status)) {
|
|
5796
|
+
errors.push(`${label}: status 只能是 active 或 disabled`);
|
|
5797
|
+
}
|
|
5798
|
+
const credentials = item.credentials || item.secret || item.secretJson || {};
|
|
5799
|
+
for (const key of ['accessKeyId', 'accessKeySecret']) {
|
|
5800
|
+
if (credentials[key] !== undefined && !isEnvReference(credentials[key])) {
|
|
5801
|
+
errors.push(`${label}.credentials.${key}: OSS 凭据必须使用环境变量引用`);
|
|
5802
|
+
}
|
|
5803
|
+
}
|
|
5804
|
+
if (!credentials.accessKeyId || !credentials.accessKeySecret) {
|
|
5805
|
+
warnings.push(`${label}: 未声明凭据;publish 只适用于更新并保留平台已有密文`);
|
|
5806
|
+
}
|
|
5807
|
+
}
|
|
5762
5808
|
if (kind === 'authConfigs') {
|
|
5763
5809
|
const config = item.configJson || item.config || item;
|
|
5764
5810
|
if (!Array.isArray(config.methods)) {
|
|
@@ -6214,6 +6260,7 @@ async function buildResourcePlan(config, target, manifest) {
|
|
|
6214
6260
|
addPlanActions(actions, 'publicAccessPolicy', manifest.publicAccessPolicies, existing.publicAccessPolicies, (item, current) => publicAccessPolicyEquals(target.bound, item, current));
|
|
6215
6261
|
await addAutomationPlanActions(config, target, actions, manifest.automations, existing.automations);
|
|
6216
6262
|
addPlanActions(actions, 'dataView', manifest.dataViews, existing.dataViews, (item, current) => dataViewEquals(target.bound, item, current));
|
|
6263
|
+
addPlanActions(actions, 'storageConfig', manifest.storageConfigs, existing.storageConfigs, (item, current) => storageConfigEquals(item, current));
|
|
6217
6264
|
addPlanActions(actions, 'pagePermissionGroup', manifest.pagePermissionGroups, existing.pagePermissionGroups, (item, current) => pagePermissionGroupEquals(target.bound, item, current));
|
|
6218
6265
|
addPlanActions(actions, 'formPermissionGroup', manifest.formPermissionGroups, existing.formPermissionGroups, (item, current) => formPermissionGroupEquals(target.bound, item, current));
|
|
6219
6266
|
for (const item of manifest.formSettings || []) {
|
|
@@ -6287,6 +6334,7 @@ async function publishResourceManifest(config, target, manifest, options = {}) {
|
|
|
6287
6334
|
await publishRouteResources(config, target, manifest.routes || [], result, publishOptions);
|
|
6288
6335
|
await publishAutomationResources(config, target, manifest.automations || [], result, publishOptions);
|
|
6289
6336
|
await publishDataViewResources(config, target, manifest.dataViews || [], result, publishOptions);
|
|
6337
|
+
await publishStorageConfigResources(config, target, manifest.storageConfigs || [], result, publishOptions);
|
|
6290
6338
|
await publishPublicAccessPolicyResources(config, target, manifest.publicAccessPolicies || [], result, publishOptions);
|
|
6291
6339
|
await publishPagePermissionGroupResources(config, target, manifest.pagePermissionGroups || [], result, publishOptions);
|
|
6292
6340
|
await publishFormPermissionGroupResources(config, target, manifest.formPermissionGroups || [], result, publishOptions);
|
|
@@ -6314,6 +6362,7 @@ async function fetchExistingResourceMaps(config, target, manifest) {
|
|
|
6314
6362
|
publicAccessPolicies: new Map(),
|
|
6315
6363
|
automations: new Map(),
|
|
6316
6364
|
dataViews: new Map(),
|
|
6365
|
+
storageConfigs: new Map(),
|
|
6317
6366
|
pagePermissionGroups: new Map(),
|
|
6318
6367
|
formPermissionGroups: new Map(),
|
|
6319
6368
|
};
|
|
@@ -6495,6 +6544,31 @@ async function fetchExistingResourceMaps(config, target, manifest) {
|
|
|
6495
6544
|
});
|
|
6496
6545
|
}
|
|
6497
6546
|
}
|
|
6547
|
+
if ((manifest.storageConfigs || []).length > 0) {
|
|
6548
|
+
const data = await requestWithAuth(
|
|
6549
|
+
config,
|
|
6550
|
+
target.profileName,
|
|
6551
|
+
apiPathWithQuery(`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs`, {
|
|
6552
|
+
page: 1,
|
|
6553
|
+
pageSize: 1000,
|
|
6554
|
+
})
|
|
6555
|
+
);
|
|
6556
|
+
indexByCode(maps.storageConfigs, normalizeItems(data), item => item.code || item.resourceCode);
|
|
6557
|
+
for (const item of manifest.storageConfigs || []) {
|
|
6558
|
+
const code = item.code || item.resourceCode;
|
|
6559
|
+
const existing = maps.storageConfigs.get(code);
|
|
6560
|
+
if (!existing) continue;
|
|
6561
|
+
const detail = await requestOptionalWithAuth(
|
|
6562
|
+
config,
|
|
6563
|
+
target.profileName,
|
|
6564
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`
|
|
6565
|
+
);
|
|
6566
|
+
maps.storageConfigs.set(code, {
|
|
6567
|
+
...existing,
|
|
6568
|
+
...(detail || {}),
|
|
6569
|
+
});
|
|
6570
|
+
}
|
|
6571
|
+
}
|
|
6498
6572
|
if ((manifest.pagePermissionGroups || []).length > 0) {
|
|
6499
6573
|
const data = await requestWithAuth(
|
|
6500
6574
|
config,
|
|
@@ -7246,6 +7320,43 @@ async function publishDataViewResources(config, target, dataViews, result, optio
|
|
|
7246
7320
|
}
|
|
7247
7321
|
}
|
|
7248
7322
|
|
|
7323
|
+
async function publishStorageConfigResources(config, target, storageConfigs, result, options = {}) {
|
|
7324
|
+
for (const storageItem of storageConfigs) {
|
|
7325
|
+
const code = storageItem.code || storageItem.resourceCode;
|
|
7326
|
+
if (shouldSkipNoopResource(options, 'storageConfig', code)) {
|
|
7327
|
+
recordNoopResource(result, 'storageConfig', code, options);
|
|
7328
|
+
continue;
|
|
7329
|
+
}
|
|
7330
|
+
const existing = await findExistingStorageConfig(config, target, code);
|
|
7331
|
+
const body = normalizeStorageConfigManifest(storageItem);
|
|
7332
|
+
const data = existing
|
|
7333
|
+
? await requestWithAuth(
|
|
7334
|
+
config,
|
|
7335
|
+
target.profileName,
|
|
7336
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`,
|
|
7337
|
+
{ method: 'PUT', body }
|
|
7338
|
+
)
|
|
7339
|
+
: await requestWithAuth(
|
|
7340
|
+
config,
|
|
7341
|
+
target.profileName,
|
|
7342
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs`,
|
|
7343
|
+
{ method: 'POST', body }
|
|
7344
|
+
);
|
|
7345
|
+
if (data?.id) {
|
|
7346
|
+
saveStorageConfigResource(target, data.code || code, data.id, {
|
|
7347
|
+
provider: data.provider || body.provider,
|
|
7348
|
+
status: data.status || body.status,
|
|
7349
|
+
});
|
|
7350
|
+
}
|
|
7351
|
+
result.published.push({
|
|
7352
|
+
kind: 'storageConfig',
|
|
7353
|
+
code,
|
|
7354
|
+
action: existing ? 'update' : 'create',
|
|
7355
|
+
id: data?.id,
|
|
7356
|
+
});
|
|
7357
|
+
}
|
|
7358
|
+
}
|
|
7359
|
+
|
|
7249
7360
|
async function publishDataViewPermissionGroups(config, target, dataViewCode, permissionGroups) {
|
|
7250
7361
|
await requestWithAuth(
|
|
7251
7362
|
config,
|
|
@@ -7398,6 +7509,18 @@ async function findExistingDataView(config, target, code) {
|
|
|
7398
7509
|
return null;
|
|
7399
7510
|
}
|
|
7400
7511
|
|
|
7512
|
+
async function findExistingStorageConfig(config, target, code) {
|
|
7513
|
+
const stateId = target.bound.resources?.storageConfigs?.[code]?.storageConfigId;
|
|
7514
|
+
const byCode = await requestOptionalWithAuth(
|
|
7515
|
+
config,
|
|
7516
|
+
target.profileName,
|
|
7517
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`
|
|
7518
|
+
);
|
|
7519
|
+
if (byCode?.id) return byCode;
|
|
7520
|
+
if (stateId) return { id: stateId, code };
|
|
7521
|
+
return null;
|
|
7522
|
+
}
|
|
7523
|
+
|
|
7401
7524
|
async function findExistingAutomation(config, target, code) {
|
|
7402
7525
|
const stateId = target.bound.resources?.automations?.[code]?.automationId;
|
|
7403
7526
|
if (stateId) {
|
|
@@ -7545,6 +7668,7 @@ async function pruneResourceManifest(config, target, manifest, result) {
|
|
|
7545
7668
|
await pruneAuthConfigs(config, target, desiredCodes(manifest.authConfigs), result);
|
|
7546
7669
|
await pruneRoutes(config, target, desiredCodes(manifest.routes), result);
|
|
7547
7670
|
await pruneDataViews(config, target, desiredCodes(manifest.dataViews), result);
|
|
7671
|
+
await pruneStorageConfigs(config, target, desiredCodes(manifest.storageConfigs), result);
|
|
7548
7672
|
await prunePublicAccessPolicies(
|
|
7549
7673
|
config,
|
|
7550
7674
|
target,
|
|
@@ -7722,6 +7846,29 @@ async function pruneDataViews(config, target, desired, result) {
|
|
|
7722
7846
|
}
|
|
7723
7847
|
}
|
|
7724
7848
|
|
|
7849
|
+
async function pruneStorageConfigs(config, target, desired, result) {
|
|
7850
|
+
const data = await requestWithAuth(
|
|
7851
|
+
config,
|
|
7852
|
+
target.profileName,
|
|
7853
|
+
apiPathWithQuery(`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs`, {
|
|
7854
|
+
page: 1,
|
|
7855
|
+
pageSize: 1000,
|
|
7856
|
+
})
|
|
7857
|
+
);
|
|
7858
|
+
for (const item of normalizeItems(data)) {
|
|
7859
|
+
const code = item.code || item.resourceCode;
|
|
7860
|
+
if (!code || desired.has(code)) continue;
|
|
7861
|
+
await pruneOne(config, target, result, 'storageConfig', code, item.id, async () => {
|
|
7862
|
+
await requestWithAuth(
|
|
7863
|
+
config,
|
|
7864
|
+
target.profileName,
|
|
7865
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`,
|
|
7866
|
+
{ method: 'DELETE' }
|
|
7867
|
+
);
|
|
7868
|
+
});
|
|
7869
|
+
}
|
|
7870
|
+
}
|
|
7871
|
+
|
|
7725
7872
|
async function pruneFunctions(config, target, desired, result) {
|
|
7726
7873
|
const data = await requestWithAuth(
|
|
7727
7874
|
config,
|
|
@@ -7893,6 +8040,7 @@ function removeStateResource(target, kind, code) {
|
|
|
7893
8040
|
route: 'routes',
|
|
7894
8041
|
publicAccessPolicy: 'publicAccessPolicies',
|
|
7895
8042
|
dataView: 'dataViews',
|
|
8043
|
+
storageConfig: 'storageConfigs',
|
|
7896
8044
|
pagePermissionGroup: 'pagePermissionGroups',
|
|
7897
8045
|
formPermissionGroup: 'formPermissionGroups',
|
|
7898
8046
|
};
|
|
@@ -8165,6 +8313,26 @@ async function pullResources(config, target) {
|
|
|
8165
8313
|
written.push(path.relative(process.cwd(), filePath));
|
|
8166
8314
|
}
|
|
8167
8315
|
|
|
8316
|
+
const storageConfigs = await requestWithAuth(
|
|
8317
|
+
config,
|
|
8318
|
+
target.profileName,
|
|
8319
|
+
apiPathWithQuery(`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs`, {
|
|
8320
|
+
page: 1,
|
|
8321
|
+
pageSize: 1000,
|
|
8322
|
+
})
|
|
8323
|
+
);
|
|
8324
|
+
for (const storageConfig of normalizeItems(storageConfigs)) {
|
|
8325
|
+
const code = storageConfig.code || storageConfig.resourceCode || storageConfig.id;
|
|
8326
|
+
const detail = await requestWithAuth(
|
|
8327
|
+
config,
|
|
8328
|
+
target.profileName,
|
|
8329
|
+
`/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`
|
|
8330
|
+
);
|
|
8331
|
+
const filePath = path.join(baseDir, 'storage', `${code}.json`);
|
|
8332
|
+
writeResourceJsonFile(filePath, toPulledStorageConfig(detail));
|
|
8333
|
+
written.push(path.relative(process.cwd(), filePath));
|
|
8334
|
+
}
|
|
8335
|
+
|
|
8168
8336
|
const pageGroups = await requestWithAuth(
|
|
8169
8337
|
config,
|
|
8170
8338
|
target.profileName,
|
|
@@ -8407,6 +8575,18 @@ function toPulledAuthConfig(authConfig) {
|
|
|
8407
8575
|
});
|
|
8408
8576
|
}
|
|
8409
8577
|
|
|
8578
|
+
function toPulledStorageConfig(storageConfig) {
|
|
8579
|
+
return stripUndefinedValues({
|
|
8580
|
+
code: storageConfig.code || storageConfig.resourceCode,
|
|
8581
|
+
name: storageConfig.name,
|
|
8582
|
+
description: storageConfig.description || '',
|
|
8583
|
+
provider: storageConfig.provider || 'oss',
|
|
8584
|
+
status: storageConfig.status || 'active',
|
|
8585
|
+
configJson: storageConfig.configJson || storageConfig.config || {},
|
|
8586
|
+
credentialStatus: storageConfig.credentials || storageConfig.credentialStatus || undefined,
|
|
8587
|
+
});
|
|
8588
|
+
}
|
|
8589
|
+
|
|
8410
8590
|
function rewriteDataViewDefinitionForManifest(definition, lookups) {
|
|
8411
8591
|
rewriteDataViewSourceForManifest(definition.base, lookups);
|
|
8412
8592
|
for (const join of definition.joins || []) {
|
|
@@ -8657,6 +8837,106 @@ function normalizeAuthConfigManifest(authConfig) {
|
|
|
8657
8837
|
});
|
|
8658
8838
|
}
|
|
8659
8839
|
|
|
8840
|
+
function normalizeStorageConfigManifest(storageConfig) {
|
|
8841
|
+
const code = storageConfig.code || storageConfig.resourceCode;
|
|
8842
|
+
const configJson = clonePlainJson(
|
|
8843
|
+
storageConfig.configJson ||
|
|
8844
|
+
storageConfig.config ||
|
|
8845
|
+
withoutStorageConfigManifestMeta(storageConfig)
|
|
8846
|
+
);
|
|
8847
|
+
const credentials = normalizeStorageCredentialsForPublish(storageConfig);
|
|
8848
|
+
return stripUndefinedValues({
|
|
8849
|
+
code,
|
|
8850
|
+
name: storageConfig.name || configJson.name || code,
|
|
8851
|
+
description:
|
|
8852
|
+
storageConfig.description !== undefined
|
|
8853
|
+
? storageConfig.description
|
|
8854
|
+
: configJson.description || '',
|
|
8855
|
+
provider: storageConfig.provider || configJson.provider || 'oss',
|
|
8856
|
+
status: storageConfig.status || configJson.status || 'active',
|
|
8857
|
+
configJson: stripUndefinedValues({
|
|
8858
|
+
region: configJson.region,
|
|
8859
|
+
bucket: configJson.bucket,
|
|
8860
|
+
endpoint: configJson.endpoint,
|
|
8861
|
+
publicBaseUrl: configJson.publicBaseUrl,
|
|
8862
|
+
pathPrefix: configJson.pathPrefix,
|
|
8863
|
+
maxFileSizeMb: configJson.maxFileSizeMb,
|
|
8864
|
+
allowedExtensions: configJson.allowedExtensions,
|
|
8865
|
+
uploadUrlExpiresSeconds: configJson.uploadUrlExpiresSeconds,
|
|
8866
|
+
}),
|
|
8867
|
+
...(credentials ? { credentials } : {}),
|
|
8868
|
+
});
|
|
8869
|
+
}
|
|
8870
|
+
|
|
8871
|
+
function withoutStorageConfigManifestMeta(storageConfig) {
|
|
8872
|
+
const next = withoutResourceMeta(storageConfig);
|
|
8873
|
+
delete next.code;
|
|
8874
|
+
delete next.resourceCode;
|
|
8875
|
+
delete next.name;
|
|
8876
|
+
delete next.description;
|
|
8877
|
+
delete next.provider;
|
|
8878
|
+
delete next.status;
|
|
8879
|
+
delete next.config;
|
|
8880
|
+
delete next.configJson;
|
|
8881
|
+
delete next.credentials;
|
|
8882
|
+
delete next.secret;
|
|
8883
|
+
delete next.secretJson;
|
|
8884
|
+
delete next.credentialStatus;
|
|
8885
|
+
return next;
|
|
8886
|
+
}
|
|
8887
|
+
|
|
8888
|
+
function normalizeStorageCredentialsForPublish(storageConfig) {
|
|
8889
|
+
const source =
|
|
8890
|
+
storageConfig.credentials || storageConfig.secret || storageConfig.secretJson || {};
|
|
8891
|
+
const hasAccessKeyId = source.accessKeyId !== undefined;
|
|
8892
|
+
const hasAccessKeySecret = source.accessKeySecret !== undefined;
|
|
8893
|
+
if (!hasAccessKeyId && !hasAccessKeySecret) return null;
|
|
8894
|
+
return {
|
|
8895
|
+
accessKeyId: resolveEnvReference(source.accessKeyId, 'OSS accessKeyId'),
|
|
8896
|
+
accessKeySecret: resolveEnvReference(
|
|
8897
|
+
source.accessKeySecret,
|
|
8898
|
+
'OSS accessKeySecret'
|
|
8899
|
+
),
|
|
8900
|
+
};
|
|
8901
|
+
}
|
|
8902
|
+
|
|
8903
|
+
let cachedManifestEnv = null;
|
|
8904
|
+
|
|
8905
|
+
function getManifestEnv() {
|
|
8906
|
+
if (!cachedManifestEnv) {
|
|
8907
|
+
cachedManifestEnv = {
|
|
8908
|
+
...loadGlobalEnv(),
|
|
8909
|
+
...process.env,
|
|
8910
|
+
};
|
|
8911
|
+
}
|
|
8912
|
+
return cachedManifestEnv;
|
|
8913
|
+
}
|
|
8914
|
+
|
|
8915
|
+
function isEnvReference(value) {
|
|
8916
|
+
return Boolean(parseEnvReferenceName(value));
|
|
8917
|
+
}
|
|
8918
|
+
|
|
8919
|
+
function resolveEnvReference(value, label) {
|
|
8920
|
+
const envName = parseEnvReferenceName(value);
|
|
8921
|
+
if (!envName) fail(`${label} 必须使用环境变量引用`);
|
|
8922
|
+
const env = getManifestEnv();
|
|
8923
|
+
const resolved = env[envName];
|
|
8924
|
+
if (resolved === undefined || resolved === '') {
|
|
8925
|
+
fail(`${label} 引用的环境变量未设置: ${envName}`);
|
|
8926
|
+
}
|
|
8927
|
+
return resolved;
|
|
8928
|
+
}
|
|
8929
|
+
|
|
8930
|
+
function parseEnvReferenceName(value) {
|
|
8931
|
+
const text = String(value || '').trim();
|
|
8932
|
+
const match =
|
|
8933
|
+
text.match(/^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$/) ||
|
|
8934
|
+
text.match(/^\$([A-Za-z_][A-Za-z0-9_]*)$/) ||
|
|
8935
|
+
text.match(/^env:([A-Za-z_][A-Za-z0-9_]*)$/) ||
|
|
8936
|
+
text.match(/^\{\{env\.([A-Za-z_][A-Za-z0-9_]*)\}\}$/);
|
|
8937
|
+
return match?.[1];
|
|
8938
|
+
}
|
|
8939
|
+
|
|
8660
8940
|
function withoutAuthConfigManifestMeta(authConfig) {
|
|
8661
8941
|
const next = withoutResourceMeta(authConfig);
|
|
8662
8942
|
delete next.code;
|
|
@@ -9188,6 +9468,24 @@ function authConfigEquals(desired, existing) {
|
|
|
9188
9468
|
);
|
|
9189
9469
|
}
|
|
9190
9470
|
|
|
9471
|
+
function storageConfigEquals(desired, existing) {
|
|
9472
|
+
if (!existing) return false;
|
|
9473
|
+
const expected = normalizeStorageConfigManifest({
|
|
9474
|
+
...desired,
|
|
9475
|
+
credentials: undefined,
|
|
9476
|
+
secret: undefined,
|
|
9477
|
+
secretJson: undefined,
|
|
9478
|
+
});
|
|
9479
|
+
return (
|
|
9480
|
+
String(existing.code || existing.resourceCode || '') === String(expected.code || '') &&
|
|
9481
|
+
String(existing.name || '') === String(expected.name || '') &&
|
|
9482
|
+
String(existing.description || '') === String(expected.description || '') &&
|
|
9483
|
+
String(existing.provider || 'oss') === String(expected.provider || 'oss') &&
|
|
9484
|
+
String(existing.status || 'active') === String(expected.status || 'active') &&
|
|
9485
|
+
jsonEqualsForPlan(existing.configJson || existing.config || {}, expected.configJson || {}, desired.__dir)
|
|
9486
|
+
);
|
|
9487
|
+
}
|
|
9488
|
+
|
|
9191
9489
|
function routeEquals(desired, existing) {
|
|
9192
9490
|
if (!existing) return false;
|
|
9193
9491
|
const expected = normalizeRouteManifest(desired);
|
package/lib/workspace-init.js
CHANGED
|
@@ -59,7 +59,7 @@ AI 在实现成熟交互前必须先判断是否已有可靠组件或库:
|
|
|
59
59
|
| --- | --- | --- | --- |
|
|
60
60
|
| 选择人员 | `UserSelectField` | 直接接入组织架构 | 人员列表、搜索、按部门筛选、层级树 |
|
|
61
61
|
| 选择部门 | `DepartmentSelectField` | 直接接入组织架构 | 部门树、搜索、多选 |
|
|
62
|
-
| 上传附件 | `AttachmentField` |
|
|
62
|
+
| 上传附件 | `AttachmentField` | 接入平台存储或声明式 OSS 存储 | 上传、预览、下载、鉴权 URL 或真实 OSS URL |
|
|
63
63
|
| 上传图片 | `ImageField` | 接入平台存储 | 上传、压缩、缩略图、预览 |
|
|
64
64
|
| 富文本编辑 | `EditorField` | 含图片上传集成 | 完整工具栏、平台图床、粘贴清洗 |
|
|
65
65
|
| 数字签名 | `DigitalSignatureField` | 平台级签名 | 签名采集、验证、归档 |
|
|
@@ -75,12 +75,13 @@ import {
|
|
|
75
75
|
AttachmentField,
|
|
76
76
|
} from 'openxiangda';
|
|
77
77
|
|
|
78
|
-
<UserSelectField name="owner" label="负责人" multiple={false} />
|
|
79
|
-
<DepartmentSelectField name="dept" label="所属部门" />
|
|
80
|
-
<AttachmentField name="files" label="附件" maxCount={5} />
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
<UserSelectField name="owner" label="负责人" multiple={false} />
|
|
79
|
+
<DepartmentSelectField name="dept" label="所属部门" />
|
|
80
|
+
<AttachmentField name="files" label="附件" maxCount={5} />
|
|
81
|
+
<AttachmentField name="ossFiles" label="OSS 附件" uploadProvider="oss" storageCode="evaluate_oss" />
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
> ✅ 一句话原则:**这些场景看到了,直接抄上表,不要自己写。**
|
|
84
85
|
|
|
85
86
|
---
|
|
86
87
|
|
|
@@ -75,6 +75,7 @@ Rules:
|
|
|
75
75
|
- For `CascadeDateField`, store a date range and document whether the value is inclusive.
|
|
76
76
|
- For `UserSelectField` and `DepartmentSelectField`, do not invent user or department IDs. Use runtime/platform selection.
|
|
77
77
|
- For `AttachmentField` and `ImageField`, do not hardcode OSS URLs in defaults unless the file has already been uploaded by platform tooling.
|
|
78
|
+
- For custom OSS attachment upload, first declare a `src/resources/storage/<code>.json` resource, then set `uploadProvider: "oss"` and `storageCode: "<code>"` on `AttachmentField`. Never put OSS AK/SK values in schema, page code, or committed resource files.
|
|
78
79
|
- For `SubFormField`, use `columns` for child fields and keep child `fieldId` values stable within the subform.
|
|
79
80
|
- `TextAreaField` is accepted by workspace tools and normalized to runtime `TextareaField`; prefer `TextAreaField` in OpenXiangda docs for readability.
|
|
80
81
|
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
| 人员选择(单) | `UserSelectField` (单选) | `{"label": "张三", "value": "user_001"}` | `value.label` | `value.value` 作为 userId |
|
|
44
44
|
| 人员选择(多) | `UserSelectField` (多选) | `[{"label":"张三","value":"user_001"},{"label":"李四","value":"user_002"}]` | `items.map(i => i.label).join(', ')` | `items.map(i => i.value)` 作为 userId 列表 |
|
|
45
45
|
| 部门选择 | `DepartmentSelectField` | 单选 `{"label": "研发部", "value": "dept_001"}`;多选 `[{...}, ...]` | `value.label` 或 `items.map(i => i.label)` | `value.value` / `items.map(i => i.value)` |
|
|
46
|
-
| 附件 | `AttachmentField` | `[{"name":"文件.pdf","url":"https://...","size":1024,"type":"application/pdf"}]` | 文件名+下载链接列表 | 通过 `url`
|
|
46
|
+
| 附件 | `AttachmentField` | `[{"name":"文件.pdf","url":"https://...","size":1024,"type":"application/pdf","provider":"platform或oss","storageCode":"evaluate_oss"}]` | 文件名+下载链接列表 | 通过 `url` 下载;OSS 附件保存真实 OSS URL |
|
|
47
47
|
| 图片 | `ImageField` | `[{"name":"图片.png","url":"https://...","thumbUrl":"https://..."}]` | 缩略图网格 | 通过 `url` 预览 |
|
|
48
48
|
| 子表单 | `SubFormField` | `[{字段A: ..., 字段B: ...}, {...}]` (对象数组) | 渲染为子行表格 | 遍历每行,按字段 code 取值 |
|
|
49
49
|
| 位置 | `LocationField` | `{"address":"杭州市xxx","lng":120.12,"lat":30.27}` | `value.address` | `value.lng`/`value.lat` 用于地图 |
|
|
@@ -244,7 +244,7 @@ const filter = {
|
|
|
244
244
|
3. **提交表单时必须组装完整 `{label, value}` 结构**:仅传 value 会导致历史展示丢失中文名。
|
|
245
245
|
4. **多选字段始终是数组**,即便只有一项也写成 `[{label, value}]`;空值用 `[]`,不要用 `null`。
|
|
246
246
|
5. **`UserSelectField` / `DepartmentSelectField` 与普通 `SelectField` 的格式完全一致**,唯一区别是 `value` 语义为 userId / departmentId。
|
|
247
|
-
6. **附件 / 图片字段始终是数组**:单文件场景也是 `[{name, url, ...}]`,没有则 `[]
|
|
247
|
+
6. **附件 / 图片字段始终是数组**:单文件场景也是 `[{name, url, ...}]`,没有则 `[]`。使用 OSS 自定义上传时,附件项会额外带 `provider: "oss"`、`storageCode`、`publicUrl` 等元信息,但仍以 `url` 作为主访问地址。
|
|
248
248
|
7. **子表单 `SubFormField` 是对象数组**,每个对象代表一行,键为子字段 code。读取时遍历数组,按字段 code 访问;空子表单为 `[]`。
|
|
249
249
|
8. **不要尝试"翻译"或"规范化" label/value**:数据库存的就是最终展示格式,前后端皆然。任何二次翻译都是 bug 来源。
|
|
250
250
|
9. **流程表单的数据格式与普通表单一致**:`formData` 结构与普通表单一致,流程节点信息走另外的字段,不影响业务字段结构。
|
|
@@ -50,6 +50,7 @@ openxiangda notification template-upsert --json-file src/resources/notifications
|
|
|
50
50
|
openxiangda notification type-upsert --json-file src/resources/notifications/register.json
|
|
51
51
|
openxiangda notification preview public_register_notice --body-json '{"payload":{"title":"测试"}}'
|
|
52
52
|
|
|
53
|
+
openxiangda resource plan storage --profile <name>
|
|
53
54
|
openxiangda data-view upsert --json-file src/resources/data-views/public_lookup.json
|
|
54
55
|
openxiangda menu update public_register --json-file src/resources/menus/public_register.json --write-manifest
|
|
55
56
|
openxiangda permission audit --json
|
|
@@ -138,6 +139,44 @@ await auth.phoneCodeLogin({ phone, code, challengeId: sent.challengeId });
|
|
|
138
139
|
|
|
139
140
|
设计前必须确认启用方式、注册策略、身份匹配键、provider 边界、默认权限、安全参数、第三方配置归属。
|
|
140
141
|
|
|
142
|
+
## 1. Storage — `src/resources/storage/<code>.json`
|
|
143
|
+
|
|
144
|
+
用于给附件字段声明自定义 OSS 上传目标。manifest 里只能写环境变量引用,不能写真实 AK/SK;发布时 CLI 解析环境变量,后端密文保存。
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"code": "evaluate_oss",
|
|
149
|
+
"name": "Evaluate OSS",
|
|
150
|
+
"provider": "oss",
|
|
151
|
+
"status": "active",
|
|
152
|
+
"configJson": {
|
|
153
|
+
"region": "oss-cn-hangzhou",
|
|
154
|
+
"bucket": "evaluate-oss",
|
|
155
|
+
"publicBaseUrl": "https://evaluate-oss.oss-cn-hangzhou.aliyuncs.com",
|
|
156
|
+
"pathPrefix": "openxiangda/{{appType}}/{{yyyy}}/{{MM}}/{{dd}}",
|
|
157
|
+
"maxFileSizeMb": 20,
|
|
158
|
+
"allowedExtensions": ["txt", "pdf", "png"]
|
|
159
|
+
},
|
|
160
|
+
"credentials": {
|
|
161
|
+
"accessKeyId": "${APP_OSS_ACCESS_KEY_ID}",
|
|
162
|
+
"accessKeySecret": "${APP_OSS_ACCESS_KEY_SECRET}"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
表单字段引用:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
<AttachmentField
|
|
171
|
+
name="attachments"
|
|
172
|
+
label="附件"
|
|
173
|
+
uploadProvider="oss"
|
|
174
|
+
storageCode="evaluate_oss"
|
|
175
|
+
/>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
默认附件不配置 `uploadProvider`/`storageCode` 时仍走平台上传。OSS 附件保存真实 OSS URL;预览、下载、删除对象都通过 storage 配置对应的运行时接口处理。
|
|
179
|
+
|
|
141
180
|
## 1. Public Route — `src/resources/routes/<code>.json`
|
|
142
181
|
|
|
143
182
|
新 React SPA 公开页使用 `/view/:appType/public/*`,不要再使用旧 `?publicAccess=guest`。
|
package/package.json
CHANGED
|
@@ -252,11 +252,16 @@ interface RuntimeRequestConfig {
|
|
|
252
252
|
headers?: Record<string, string>;
|
|
253
253
|
responseType?: 'json' | 'blob';
|
|
254
254
|
}
|
|
255
|
+
interface RuntimeUploadOptions {
|
|
256
|
+
uploadProvider?: 'platform' | 'oss';
|
|
257
|
+
storageCode?: string;
|
|
258
|
+
appType?: string;
|
|
259
|
+
}
|
|
255
260
|
interface FormRuntimeApi {
|
|
256
261
|
request: <T = any>(config: RuntimeRequestConfig) => Promise<RuntimeResponse<T> | Blob>;
|
|
257
|
-
uploadFile: (file: File, bucketName?: string, onProgress?: (percent: number) => void) => Promise<AttachmentItem>;
|
|
262
|
+
uploadFile: (file: File, bucketName?: string, onProgress?: (percent: number) => void, options?: RuntimeUploadOptions) => Promise<AttachmentItem>;
|
|
258
263
|
uploadPublicFile: (file: File, bucketName?: string, onProgress?: (percent: number) => void) => Promise<AttachmentItem>;
|
|
259
|
-
deleteFile: (objectName: string, bucketName?: string) => Promise<{
|
|
264
|
+
deleteFile: (objectName: string, bucketName?: string, options?: RuntimeUploadOptions) => Promise<{
|
|
260
265
|
success: boolean;
|
|
261
266
|
}>;
|
|
262
267
|
createDownloadTicket: (bucketName: string, objectName: string, fileName?: string) => Promise<any>;
|
|
@@ -571,6 +576,9 @@ interface AttachmentItem {
|
|
|
571
576
|
id: string;
|
|
572
577
|
uid?: string;
|
|
573
578
|
status?: 'uploading' | 'done' | 'error';
|
|
579
|
+
provider?: 'platform' | 'oss';
|
|
580
|
+
storageCode?: string;
|
|
581
|
+
appType?: string;
|
|
574
582
|
objectName?: string;
|
|
575
583
|
bucketName?: string;
|
|
576
584
|
originalName?: string;
|
|
@@ -593,6 +601,8 @@ interface AttachmentFieldProps extends BaseFieldProps {
|
|
|
593
601
|
maxSize?: number;
|
|
594
602
|
uploadAction?: string;
|
|
595
603
|
bucketName?: string;
|
|
604
|
+
uploadProvider?: 'platform' | 'oss';
|
|
605
|
+
storageCode?: string;
|
|
596
606
|
multiple?: boolean;
|
|
597
607
|
allowedTypes?: string[];
|
|
598
608
|
showPreview?: boolean;
|
|
@@ -1095,4 +1105,4 @@ interface ProcessPreviewProps {
|
|
|
1095
1105
|
}
|
|
1096
1106
|
declare const ProcessPreview: React__default.FC<ProcessPreviewProps>;
|
|
1097
1107
|
|
|
1098
|
-
export { type FormRuntimeConfig as $, type AddressFieldProps as A, type BaseFieldProps as B, type CascadeDateFieldProps as C, type DataFilter as D, type DepartmentTreeNode as E, type DigitalSignatureFieldProps as F, type DigitalSignatureValue as G, type EditorChoiceOption as H, type EditorFieldProps as I, type EditorToolbarAction as J, type FieldBehavior as K, type FieldDefinition as L, type FieldLayoutNode as M, type FieldValueSyncConfig as N, type FormAppearanceConfig as O, type FormDataDeleteParams as P, type FormDataQueryParams as Q, type FormEffect as R, type FormEffectAction as S, type FormEffectCondition as T, type FormEffectConditionOperator as U, type FormEngineConfig as V, type FormEngineMode as W, type FormInstanceData as X, type FormLayoutNode as Y, type FormRuntimeApi as Z, type FormRuntimeApiConfig as _, type AddressValue as a, type
|
|
1108
|
+
export { type FormRuntimeConfig as $, type AddressFieldProps as A, type BaseFieldProps as B, type CascadeDateFieldProps as C, type DataFilter as D, type DepartmentTreeNode as E, type DigitalSignatureFieldProps as F, type DigitalSignatureValue as G, type EditorChoiceOption as H, type EditorFieldProps as I, type EditorToolbarAction as J, type FieldBehavior as K, type FieldDefinition as L, type FieldLayoutNode as M, type FieldValueSyncConfig as N, type FormAppearanceConfig as O, type FormDataDeleteParams as P, type FormDataQueryParams as Q, type FormEffect as R, type FormEffectAction as S, type FormEffectCondition as T, type FormEffectConditionOperator as U, type FormEngineConfig as V, type FormEngineMode as W, type FormInstanceData as X, type FormLayoutNode as Y, type FormRuntimeApi as Z, type FormRuntimeApiConfig as _, type AddressValue as a, type TextAreaFieldProps as a$, type FormSchema as a0, FormSection as a1, type FormSectionProps as a2, type FormSubmitBehavior as a3, type FormTemplateConfig as a4, type GridLayoutCell as a5, type GridLayoutNode as a6, type ImageFieldProps as a7, type InitiatorSelectCandidate as a8, type InitiatorSelectRequirement as a9, type ProcessStatus as aA, type ProcessTask as aB, type RadioFieldProps as aC, type ResubmitParams as aD, type ReturnParams as aE, type ReturnPolicy as aF, type ReturnableNode as aG, type ReturnableNodeResult as aH, type RuntimeDataQueryParams as aI, type RuntimeDataQueryResult as aJ, type RuntimeRequestConfig as aK, type RuntimeResponse as aL, type RuntimeUploadOptions as aM, type SaveTaskParams as aN, type SectionLayoutNode as aO, type SelectFieldProps as aP, type SerialNumberFieldProps as aQ, type SignaturePoint as aR, type StandardFormPageMode as aS, type StatusMeta as aT, type StepLayoutItem as aU, type StepsLayoutNode as aV, type SubFormColumn as aW, type SubFormFieldProps as aX, type TabLayoutItem as aY, type TabsLayoutNode as aZ, type TaskStatus as a_, type InitiatorSelectScope as aa, type InitiatorSelectedApprovers as ab, type JSONFieldProps as ac, type LayoutVisibleWhen as ad, type LinkedFormOptionConfig as ae, type LocationFieldProps as af, type LocationValue as ag, type LowcodePageMeta as ah, type LowcodePageNode as ai, type LowcodePageNodeType as aj, type LowcodePageSchema as ak, type MultiSelectFieldProps as al, type NumberFieldProps as am, type OptionItem as an, type OptionSourceConfig as ao, type OptionSourceType as ap, type PeopleShortcutConfig as aq, type PeopleShortcutType as ar, type PreviewParams as as, type ProcessAction as at, type ProcessBasicInfo as au, type ProcessDefinition as av, type ProcessNodeType as aw, ProcessPreview as ax, type ProcessPreviewProps as ay, type ProcessRoute as az, type ApprovalActionType as b, type TextFieldProps as b0, type TextShortcutConfig as b1, type TextShortcutType as b2, type TransferParams as b3, type UserDisplayFormat as b4, type UserItem as b5, type UserSelectFieldProps as b6, type ValidationPreset as b7, type ValidationRule as b8, type ViewPermissionQueryParams as b9, type ViewPermissionSummary as ba, type WithdrawParams as bb, type ApprovalPermission as c, ApprovalTimeline as d, type ApprovalTimelineProps as e, type ApproveParams as f, type AssociationFormConfig as g, type AssociationFormFieldProps as h, type AssociationValue as i, type AttachmentFieldProps as j, type AttachmentItem as k, type BaseLayoutNode as l, type CascadeSelectFieldProps as m, type ChangeRecord as n, type ChangeRecordListResponse as o, type ChangeRecordQueryParams as p, type CheckboxFieldProps as q, type DataLinkageCondition as r, type DataLinkageConfig as s, type DateFieldProps as t, type DateRangeRestriction as u, type DateRestrictionConfig as v, type DateShortcutConfig as w, type DateShortcutType as x, type DefaultValueLinkageConfig as y, type DepartmentSelectFieldProps as z };
|