@skopon-cool/form-sdk 0.6.3 → 0.6.5
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/dist/adapter/a2uiAdapter.d.ts +1 -1
- package/dist/adapter/a2uiAdapter.d.ts.map +1 -1
- package/dist/adapter/formAssetOptions.d.ts +3 -0
- package/dist/adapter/formAssetOptions.d.ts.map +1 -0
- package/dist/adapter/formSchema.d.ts.map +1 -1
- package/dist/adapter/resolveSurface.d.ts +1 -1
- package/dist/adapter/resolveSurface.d.ts.map +1 -1
- package/dist/catalog/a2uiCustomCatalog.d.ts.map +1 -1
- package/dist/catalog/materialUploadContext.d.ts +24 -0
- package/dist/catalog/materialUploadContext.d.ts.map +1 -0
- package/dist/components/AskUserFormCard.d.ts +5 -0
- package/dist/components/AskUserFormCard.d.ts.map +1 -1
- package/dist/components/SkoponFormRenderer.d.ts +3 -0
- package/dist/components/SkoponFormRenderer.d.ts.map +1 -1
- package/dist/form-sdk.css +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2170 -1928
- package/dist/submit/buildAnswerAgentBody.d.ts.map +1 -1
- package/dist/submit/intersectPayloadBlocksWithForm.d.ts +11 -2
- package/dist/submit/intersectPayloadBlocksWithForm.d.ts.map +1 -1
- package/dist/types/index.d.ts +35 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapter/a2uiAdapter.test.ts +4 -0
- package/src/adapter/a2uiAdapter.ts +58 -2
- package/src/adapter/formAssetOptions.ts +19 -0
- package/src/adapter/formSchema.ts +54 -0
- package/src/adapter/resolveSurface.ts +4 -1
- package/src/catalog/a2uiCustomCatalog.tsx +296 -46
- package/src/catalog/fileUploadPreview.test.tsx +77 -11
- package/src/catalog/materialUploadContext.tsx +43 -0
- package/src/catalog/moduleTabs.test.tsx +59 -0
- package/src/components/AskUserFormCard.tsx +33 -9
- package/src/components/AskUserFormCard.upload.test.tsx +66 -0
- package/src/components/SkoponFormRenderer.tsx +6 -0
- package/src/icons/FilePlaceholderIcon.tsx +2 -2
- package/src/index.ts +2 -0
- package/src/styles/index.css +295 -0
- package/src/submit/buildAnswerAgentBody.ts +2 -0
- package/src/submit/intersectPayloadBlocksWithForm.ts +52 -3
- package/src/submit/submit.test.ts +54 -0
- package/src/types/index.ts +37 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildAnswerAgentBody.d.ts","sourceRoot":"","sources":["../../src/submit/buildAnswerAgentBody.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,kCAAkC,CAAA;AAEzC,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;
|
|
1
|
+
{"version":3,"file":"buildAnswerAgentBody.d.ts","sourceRoot":"","sources":["../../src/submit/buildAnswerAgentBody.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,kCAAkC,CAAA;AAEzC,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAqBD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,yBAAyB,CAAA;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,uBAAuB,GAAG,UAAU,GAAG,IAAI,CAAA;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,OAAO,EACP,IAAI,EACJ,MAAM,GACP,EAAE,2BAA2B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAevD;AAED,iDAAiD;AACjD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAqBpF;AAED,iCAAiC;AACjC,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,yBAAyB,GACjC,MAAM,GAAG,IAAI,CAQf"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FormBlock, FormSchema } from '../types/index';
|
|
2
|
-
export type PayloadBlocksDefinition = Pick<FormSchema, 'title' | 'description' | 'blocks'> & {
|
|
2
|
+
export type PayloadBlocksDefinition = Pick<FormSchema, 'title' | 'description' | 'modules' | 'blocks'> & {
|
|
3
|
+
schema?: 'skopon.material-form/v2';
|
|
3
4
|
/**
|
|
4
5
|
* ask 原始 blocks(normalize 前)。交集合并按此键集覆盖 form,
|
|
5
6
|
* 避免 normalize 填入的空默认值误盖表单样式。
|
|
@@ -13,6 +14,14 @@ export interface PayloadBlocksIntersection {
|
|
|
13
14
|
renderBlocks: FormBlock[];
|
|
14
15
|
title: string;
|
|
15
16
|
description: string;
|
|
17
|
+
modules?: FormSchema['modules'];
|
|
18
|
+
}
|
|
19
|
+
export interface IntersectPayloadBlocksOptions {
|
|
20
|
+
/**
|
|
21
|
+
* snapshot:消息快照中的显式配置优先(兼容旧行为);
|
|
22
|
+
* latest:最新表单负责布局/文案/校验,只保留快照里的填写与审核运行态。
|
|
23
|
+
*/
|
|
24
|
+
definitionPolicy?: 'snapshot' | 'latest';
|
|
16
25
|
}
|
|
17
26
|
/** 解析 ask_user payload 为 blocksJson 形(title / description / blocks) */
|
|
18
27
|
export declare function parsePayloadBlocksJson(payload: unknown): PayloadBlocksDefinition | null;
|
|
@@ -20,7 +29,7 @@ export declare function parsePayloadBlocksJson(payload: unknown): PayloadBlocksD
|
|
|
20
29
|
* payload.blocks 与 vt_forms 按 input 块 name 取交集用于渲染;
|
|
21
30
|
* payload 中 form 不存在的块归入 extraBlocks(不渲染,提交时写入 curl)。
|
|
22
31
|
*/
|
|
23
|
-
export declare function intersectPayloadBlocksWithForm(payloadDef: PayloadBlocksDefinition, formDefinition: FormSchema | undefined): PayloadBlocksIntersection;
|
|
32
|
+
export declare function intersectPayloadBlocksWithForm(payloadDef: PayloadBlocksDefinition, formDefinition: FormSchema | undefined, options?: IntersectPayloadBlocksOptions): PayloadBlocksIntersection;
|
|
24
33
|
/** 从 extraBlocks 提取提交值(优先 defaultValue) */
|
|
25
34
|
export declare function extractExtraBlockValues(extraBlocks: FormBlock[]): Record<string, unknown>;
|
|
26
35
|
/** payload 是否含至少一个具 name 的 input 块(可用于卡片 fallback) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3D,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC,GAAG;
|
|
1
|
+
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAG3D,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG;IACvG,MAAM,CAAC,EAAE,yBAAyB,CAAA;IAClC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,gEAAgE;IAChE,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;CAChC;AAUD,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,gBAAgB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;CACzC;AAiGD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAsBvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,uBAAuB,EACnC,cAAc,EAAE,UAAU,GAAG,SAAS,EACtC,OAAO,CAAC,EAAE,6BAA6B,GACtC,yBAAyB,CAwC3B;AA+BD,2CAA2C;AAC3C,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzF;AAED,sDAAsD;AACtD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAOlF;AAED,yEAAyE;AACzE,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,EAAE,CAQ3F;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,EAAE,CASvF;AAED,6DAA6D;AAC7D,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,uBAAuB,GAClC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
export type A2uiBinding<T> = T | {
|
|
5
5
|
path: string;
|
|
6
6
|
};
|
|
7
|
-
export type A2uiComponentName = 'Column' | 'Row' | 'Text' | 'Image' | 'Video' | 'AudioPlayer' | 'TextField' | 'CheckBox' | 'ChoicePicker' | 'DateTimeInput' | 'FileUpload' | 'SkoponMedia' | 'SkoponWeb' | 'SkoponSelect' | 'SkoponResumeSelect' | 'SkoponCaseSelect';
|
|
7
|
+
export type A2uiComponentName = 'Column' | 'Row' | 'Text' | 'Image' | 'Video' | 'AudioPlayer' | 'TextField' | 'CheckBox' | 'ChoicePicker' | 'DateTimeInput' | 'FileUpload' | 'SkoponMedia' | 'SkoponWeb' | 'SkoponSelect' | 'SkoponResumeSelect' | 'SkoponCaseSelect' | 'SkoponModulePanel';
|
|
8
|
+
/** 表单分组模块。运行时以 Tab 展示,要求与示例统一放在模块底部。 */
|
|
9
|
+
export interface FormModule {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
reviewCriteria?: string;
|
|
14
|
+
exampleUrls?: string[];
|
|
15
|
+
}
|
|
8
16
|
export interface A2uiComponentNode {
|
|
9
17
|
id: string;
|
|
10
18
|
component: A2uiComponentName | string;
|
|
@@ -31,6 +39,13 @@ export interface FormBlockOption {
|
|
|
31
39
|
value: string;
|
|
32
40
|
label: string;
|
|
33
41
|
}
|
|
42
|
+
export interface FormAssetOption {
|
|
43
|
+
assetId: string;
|
|
44
|
+
url: string;
|
|
45
|
+
previewUrl?: string;
|
|
46
|
+
label: string;
|
|
47
|
+
assetType?: string;
|
|
48
|
+
}
|
|
34
49
|
export type FormConditionOperator = 'eq' | 'ne' | 'empty' | 'notEmpty';
|
|
35
50
|
export interface FormBlockCondition {
|
|
36
51
|
fieldName: string;
|
|
@@ -103,6 +118,21 @@ export interface FormBlock {
|
|
|
103
118
|
fileExampleUrls?: string[];
|
|
104
119
|
/** 制作模板的逐字段审核标准;由工作流读取,不能使用提交值覆盖。 */
|
|
105
120
|
fileReviewCriteria?: string;
|
|
121
|
+
/** 是否需要由工作流审核上传内容;素材库已审核素材可以关闭。 */
|
|
122
|
+
fileReviewRequired?: boolean;
|
|
123
|
+
/** 物料采集来源模式,由 skopon-admin 环节配置。 */
|
|
124
|
+
fileSourceMode?: 'upload_required' | 'upload_or_asset' | 'asset_only';
|
|
125
|
+
/** 通用收集流从 Footage 为当前素材位查询的候选;提交选中的素材 ID。 */
|
|
126
|
+
fileAssetOptions?: FormAssetOption[];
|
|
127
|
+
/** 对应 Footage 同步素材位的限定 key。 */
|
|
128
|
+
assetSlotKey?: string;
|
|
129
|
+
assetType?: 'image' | 'video' | 'audio' | 'text';
|
|
130
|
+
/** 运行时素材审核状态;用于返工表单回显,不作为用户提交值。 */
|
|
131
|
+
fileReviewStatus?: 'passed' | 'failed';
|
|
132
|
+
/** 运行时素材审核说明;failed 时通常为不合格原因。 */
|
|
133
|
+
fileReviewMessage?: string;
|
|
134
|
+
/** 审核未通过的历史文件,仅作错误态回显,不计入有效提交。 */
|
|
135
|
+
fileRejectedUrls?: string[];
|
|
106
136
|
defaultValue?: string | string[] | boolean;
|
|
107
137
|
/** 派生 JSON Schema 时写入 property.$comment */
|
|
108
138
|
jsonSchemaDescription?: string;
|
|
@@ -133,10 +163,13 @@ export interface FormBlock {
|
|
|
133
163
|
/** 案例单选:列表筛选条件(持久化进 block json) */
|
|
134
164
|
caseFilter?: FormCaseFilter;
|
|
135
165
|
condition?: FormBlockCondition;
|
|
166
|
+
/** 所属模块;命中 FormSchema.modules.id 时在对应 Tab 中展示。 */
|
|
167
|
+
moduleId?: string;
|
|
136
168
|
}
|
|
137
169
|
export interface FormSchema {
|
|
138
170
|
title?: string;
|
|
139
171
|
description?: string;
|
|
172
|
+
modules?: FormModule[];
|
|
140
173
|
blocks: FormBlock[];
|
|
141
174
|
jsonSchema: FormJsonSchema;
|
|
142
175
|
}
|
|
@@ -150,6 +183,7 @@ export declare function supportsDefaultValue(type: FormBlockType): boolean;
|
|
|
150
183
|
export interface FormDefinitionPayload {
|
|
151
184
|
title?: string;
|
|
152
185
|
description?: string;
|
|
186
|
+
modules?: FormModule[];
|
|
153
187
|
blocks?: FormBlock[];
|
|
154
188
|
a2ui?: A2uiSurfaceDoc;
|
|
155
189
|
json_schema?: FormJsonSchema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjD,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,KAAK,GACL,MAAM,GACN,OAAO,GACP,OAAO,GACP,aAAa,GACb,WAAW,GACX,UAAU,GACV,cAAc,GACd,eAAe,GACf,YAAY,GACZ,aAAa,GACb,WAAW,GACX,cAAc,GACd,oBAAoB,GACpB,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -49,11 +49,15 @@ describe('a2uiAdapter blocks <-> surface', () => {
|
|
|
49
49
|
id: 'material', type: 'file', name: 'image01', help: '上传人物',
|
|
50
50
|
fileExampleUrls: [' https://cdn.test/example.jpg ', 'javascript:alert(1)', 'https://cdn.test/example.jpg'],
|
|
51
51
|
fileReviewCriteria: ' 五官清晰 ',
|
|
52
|
+
fileReviewStatus: 'failed', fileReviewMessage: ' 面部模糊 ',
|
|
53
|
+
fileRejectedUrls: ['https://cdn.test/rejected.jpg'],
|
|
52
54
|
}] })
|
|
53
55
|
const back = a2uiToBlocks(blocksToA2ui(definition))
|
|
54
56
|
expect(back.blocks[0]).toMatchObject({
|
|
55
57
|
name: 'image01', help: '上传人物', fileReviewCriteria: '五官清晰',
|
|
56
58
|
fileExampleUrls: ['https://cdn.test/example.jpg'],
|
|
59
|
+
fileReviewStatus: 'failed', fileReviewMessage: '面部模糊',
|
|
60
|
+
fileRejectedUrls: ['https://cdn.test/rejected.jpg'],
|
|
57
61
|
})
|
|
58
62
|
})
|
|
59
63
|
it('blocksToA2ui builds a Column root referencing all components', () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeAssetOptions } from './formAssetOptions'
|
|
1
2
|
import type {
|
|
2
3
|
A2uiComponentNode,
|
|
3
4
|
A2uiSurfaceDoc,
|
|
@@ -279,6 +280,14 @@ function blockToComponent(block: FormBlock): {
|
|
|
279
280
|
help: block.help ?? '',
|
|
280
281
|
fileExampleUrls: block.fileExampleUrls ?? [],
|
|
281
282
|
fileReviewCriteria: block.fileReviewCriteria ?? '',
|
|
283
|
+
fileReviewRequired: block.fileReviewRequired !== false,
|
|
284
|
+
fileSourceMode: block.fileSourceMode,
|
|
285
|
+
fileAssetOptions: block.fileAssetOptions ?? [],
|
|
286
|
+
assetSlotKey: block.assetSlotKey,
|
|
287
|
+
assetType: block.assetType,
|
|
288
|
+
fileReviewStatus: block.fileReviewStatus,
|
|
289
|
+
fileReviewMessage: block.fileReviewMessage ?? '',
|
|
290
|
+
fileRejectedUrls: block.fileRejectedUrls ?? [],
|
|
282
291
|
accept: (block.fileAcceptExtensions ?? []).join(','),
|
|
283
292
|
fileAcceptTypes: block.fileAcceptTypes ?? [],
|
|
284
293
|
filePlaceholderIcon: block.filePlaceholderIcon ?? 'document',
|
|
@@ -310,12 +319,15 @@ export function isA2uiSurfaceEmpty(doc: A2uiSurfaceDoc | null | undefined): bool
|
|
|
310
319
|
|
|
311
320
|
/** FormBlock[] -> A2UI surface 文档 */
|
|
312
321
|
export function blocksToA2ui(
|
|
313
|
-
definition: Pick<FormSchema, 'title' | 'description' | 'blocks'>,
|
|
322
|
+
definition: Pick<FormSchema, 'title' | 'description' | 'modules' | 'blocks'>,
|
|
314
323
|
options?: BlocksToA2uiOptions,
|
|
315
324
|
): A2uiSurfaceDoc {
|
|
316
325
|
const components: A2uiComponentNode[] = []
|
|
317
326
|
const childIds: string[] = []
|
|
318
327
|
const dataModel: Record<string, unknown> = {}
|
|
328
|
+
const modules = definition.modules ?? []
|
|
329
|
+
const moduleById = new Map(modules.map((module) => [module.id, module]))
|
|
330
|
+
const moduleChildIds = new Map(modules.map((module) => [module.id, [] as string[]]))
|
|
319
331
|
|
|
320
332
|
const includeHeader = options?.includeHeader !== false
|
|
321
333
|
const title = (definition.title ?? '').trim()
|
|
@@ -335,8 +347,40 @@ export function blocksToA2ui(
|
|
|
335
347
|
// hidden 等无节点块仍可写入 dataModel,保证「不展示仍提交」
|
|
336
348
|
if (dataKey) dataModel[dataKey] = dataValue
|
|
337
349
|
if (!node) continue
|
|
350
|
+
const moduleId = block.moduleId?.trim()
|
|
351
|
+
if (moduleId && moduleById.has(moduleId) && node.component === 'FileUpload') {
|
|
352
|
+
// 分组表单把公共说明集中放在 Tab 底部,避免每个上传位重复拉长页面。
|
|
353
|
+
node.fileExampleUrls = []
|
|
354
|
+
node.fileReviewCriteria = ''
|
|
355
|
+
node.compact = true
|
|
356
|
+
}
|
|
338
357
|
components.push(node)
|
|
339
|
-
|
|
358
|
+
if (moduleId && moduleChildIds.has(moduleId)) {
|
|
359
|
+
moduleChildIds.get(moduleId)!.push(node.id)
|
|
360
|
+
} else {
|
|
361
|
+
childIds.push(node.id)
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const tabs = modules.flatMap((module) => {
|
|
366
|
+
const children = moduleChildIds.get(module.id) ?? []
|
|
367
|
+
if (children.length === 0) return []
|
|
368
|
+
const panelId = `__module_panel_${module.id}`
|
|
369
|
+
components.push({
|
|
370
|
+
id: panelId,
|
|
371
|
+
component: 'SkoponModulePanel',
|
|
372
|
+
children,
|
|
373
|
+
single: children.length === 1,
|
|
374
|
+
description: module.description ?? '',
|
|
375
|
+
requirementsTitle: `${module.label.replace(/(.*?)|\(.*?\)/g, '').trim()}素材要求`,
|
|
376
|
+
reviewCriteria: module.reviewCriteria ?? '',
|
|
377
|
+
exampleUrls: module.exampleUrls ?? [],
|
|
378
|
+
})
|
|
379
|
+
return [{ title: module.label, child: panelId }]
|
|
380
|
+
})
|
|
381
|
+
if (tabs.length > 0) {
|
|
382
|
+
components.push({ id: '__modules__', component: 'Tabs', tabs })
|
|
383
|
+
childIds.push('__modules__')
|
|
340
384
|
}
|
|
341
385
|
|
|
342
386
|
components.unshift({ id: ROOT_ID, component: 'Column', children: childIds })
|
|
@@ -453,6 +497,18 @@ function componentToBlock(node: A2uiComponentNode): FormBlock | null {
|
|
|
453
497
|
const block: FormBlock = { ...base('file'), name }
|
|
454
498
|
block.help = asLiteral(node.help)
|
|
455
499
|
block.fileReviewCriteria = asLiteral(node.fileReviewCriteria)
|
|
500
|
+
block.fileReviewRequired = node.fileReviewRequired !== false
|
|
501
|
+
if (node.fileSourceMode === 'upload_required' || node.fileSourceMode === 'upload_or_asset' || node.fileSourceMode === 'asset_only') block.fileSourceMode = node.fileSourceMode
|
|
502
|
+
block.fileAssetOptions = normalizeAssetOptions(node.fileAssetOptions)
|
|
503
|
+
block.assetSlotKey = asLiteral(node.assetSlotKey)
|
|
504
|
+
if (node.assetType === 'image' || node.assetType === 'video' || node.assetType === 'audio' || node.assetType === 'text') block.assetType = node.assetType
|
|
505
|
+
if (node.fileReviewStatus === 'passed' || node.fileReviewStatus === 'failed') {
|
|
506
|
+
block.fileReviewStatus = node.fileReviewStatus
|
|
507
|
+
}
|
|
508
|
+
block.fileReviewMessage = asLiteral(node.fileReviewMessage)
|
|
509
|
+
if (Array.isArray(node.fileRejectedUrls)) {
|
|
510
|
+
block.fileRejectedUrls = node.fileRejectedUrls.filter((url): url is string => typeof url === 'string')
|
|
511
|
+
}
|
|
456
512
|
if (Array.isArray(node.fileExampleUrls)) {
|
|
457
513
|
block.fileExampleUrls = node.fileExampleUrls.filter((url): url is string => typeof url === 'string')
|
|
458
514
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FormAssetOption } from '../types/index'
|
|
2
|
+
|
|
3
|
+
export function normalizeAssetOptions(raw: unknown): FormAssetOption[] {
|
|
4
|
+
if (!Array.isArray(raw)) return []
|
|
5
|
+
const seen = new Set<string>()
|
|
6
|
+
return raw.slice(0, 100).flatMap((item) => {
|
|
7
|
+
if (!item || typeof item !== 'object') return []
|
|
8
|
+
const assetId = String(item.assetId ?? '').trim()
|
|
9
|
+
const url = typeof item.url === 'string' ? item.url.trim() : ''
|
|
10
|
+
if (!assetId || seen.has(assetId) || !/^https?:\/\//i.test(url)) return []
|
|
11
|
+
seen.add(assetId)
|
|
12
|
+
return [{
|
|
13
|
+
assetId, url,
|
|
14
|
+
label: typeof item.label === 'string' ? item.label : `素材 ${assetId}`,
|
|
15
|
+
previewUrl: typeof item.previewUrl === 'string' && /^https?:\/\//i.test(item.previewUrl) ? item.previewUrl : undefined,
|
|
16
|
+
assetType: typeof item.assetType === 'string' ? item.assetType : undefined,
|
|
17
|
+
}]
|
|
18
|
+
})
|
|
19
|
+
}
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
FormContentFilter,
|
|
6
6
|
FormResumeFilter,
|
|
7
7
|
FormJsonSchema,
|
|
8
|
+
FormModule,
|
|
8
9
|
FormSchema,
|
|
9
10
|
} from '../types/index'
|
|
10
11
|
import {
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
} from './formMedia'
|
|
26
27
|
import { FORM_WEB_DEFAULT_HEIGHT, normalizeWebHeight } from './formWeb'
|
|
27
28
|
import { hasRenderableFormOptions, normalizeFormOptions } from './formOptions'
|
|
29
|
+
import { normalizeAssetOptions } from './formAssetOptions'
|
|
28
30
|
|
|
29
31
|
const DEFAULT_MEDIA_URL_MAX = 10
|
|
30
32
|
|
|
@@ -194,6 +196,7 @@ function normalizeBlock(raw: FormBlock): FormBlock {
|
|
|
194
196
|
return {
|
|
195
197
|
id: migrated.id?.trim() || generateId('block-'),
|
|
196
198
|
type,
|
|
199
|
+
moduleId: migrated.moduleId?.trim() || undefined,
|
|
197
200
|
name: migrated.name?.trim() || undefined,
|
|
198
201
|
label: migrated.label ?? '',
|
|
199
202
|
placeholder: migrated.placeholder ?? '',
|
|
@@ -219,6 +222,24 @@ function normalizeBlock(raw: FormBlock): FormBlock {
|
|
|
219
222
|
).map((url) => url.trim()))]
|
|
220
223
|
: undefined,
|
|
221
224
|
fileReviewCriteria: type === 'file' ? migrated.fileReviewCriteria?.trim() ?? '' : undefined,
|
|
225
|
+
fileReviewRequired: type === 'file' ? migrated.fileReviewRequired !== false : undefined,
|
|
226
|
+
fileSourceMode: type === 'file' && ['upload_required', 'upload_or_asset', 'asset_only'].includes(String(migrated.fileSourceMode))
|
|
227
|
+
? migrated.fileSourceMode
|
|
228
|
+
: undefined,
|
|
229
|
+
fileAssetOptions: type === 'file' ? normalizeAssetOptions(migrated.fileAssetOptions) : undefined,
|
|
230
|
+
assetSlotKey: type === 'file' ? migrated.assetSlotKey?.trim() || undefined : undefined,
|
|
231
|
+
assetType: type === 'file' && ['image', 'video', 'audio', 'text'].includes(String(migrated.assetType))
|
|
232
|
+
? migrated.assetType
|
|
233
|
+
: undefined,
|
|
234
|
+
fileReviewStatus: type === 'file' && (migrated.fileReviewStatus === 'passed' || migrated.fileReviewStatus === 'failed')
|
|
235
|
+
? migrated.fileReviewStatus
|
|
236
|
+
: undefined,
|
|
237
|
+
fileReviewMessage: type === 'file' ? migrated.fileReviewMessage?.trim() ?? '' : undefined,
|
|
238
|
+
fileRejectedUrls: type === 'file' && Array.isArray(migrated.fileRejectedUrls)
|
|
239
|
+
? [...new Set(migrated.fileRejectedUrls.filter((url): url is string =>
|
|
240
|
+
typeof url === 'string' && /^https?:\/\//i.test(url.trim()),
|
|
241
|
+
).map((url) => url.trim()))]
|
|
242
|
+
: undefined,
|
|
222
243
|
defaultValue: normalizeDefaultValue(type, migrated.defaultValue),
|
|
223
244
|
jsonSchemaDescription: migrated.jsonSchemaDescription?.trim() ?? '',
|
|
224
245
|
hidden: type === 'text' ? migrated.hidden === true : undefined,
|
|
@@ -438,19 +459,52 @@ export function syncFormDefinition(definition: FormSchema): FormSchema {
|
|
|
438
459
|
return {
|
|
439
460
|
title,
|
|
440
461
|
description,
|
|
462
|
+
modules: definition.modules,
|
|
441
463
|
blocks: definition.blocks,
|
|
442
464
|
jsonSchema: blocksToJsonSchema(definition.blocks, title, description),
|
|
443
465
|
}
|
|
444
466
|
}
|
|
445
467
|
|
|
468
|
+
function normalizeModules(raw: FormModule[] | undefined): FormModule[] | undefined {
|
|
469
|
+
if (!Array.isArray(raw)) return undefined
|
|
470
|
+
const ids = new Set<string>()
|
|
471
|
+
const modules: FormModule[] = []
|
|
472
|
+
for (const item of raw) {
|
|
473
|
+
if (!item || typeof item !== 'object') continue
|
|
474
|
+
const id = item.id?.trim()
|
|
475
|
+
const label = item.label?.trim()
|
|
476
|
+
if (!id || !label || ids.has(id)) continue
|
|
477
|
+
ids.add(id)
|
|
478
|
+
const exampleUrls = Array.isArray(item.exampleUrls)
|
|
479
|
+
? [...new Set(item.exampleUrls
|
|
480
|
+
.filter((url): url is string => typeof url === 'string' && /^https?:\/\//i.test(url.trim()))
|
|
481
|
+
.map((url) => url.trim()))]
|
|
482
|
+
: undefined
|
|
483
|
+
modules.push({
|
|
484
|
+
id,
|
|
485
|
+
label,
|
|
486
|
+
description: item.description?.trim() || undefined,
|
|
487
|
+
reviewCriteria: item.reviewCriteria?.trim() || undefined,
|
|
488
|
+
exampleUrls,
|
|
489
|
+
})
|
|
490
|
+
}
|
|
491
|
+
return modules.length > 0 ? modules : undefined
|
|
492
|
+
}
|
|
493
|
+
|
|
446
494
|
export function normalizeFormDefinition(raw: FormSchema | undefined): FormSchema {
|
|
447
495
|
if (!raw || !Array.isArray(raw.blocks)) {
|
|
448
496
|
return syncFormDefinition({ title: '', description: '', blocks: [], jsonSchema: {} })
|
|
449
497
|
}
|
|
450
498
|
const blocks = raw.blocks.map(normalizeBlock)
|
|
499
|
+
const modules = normalizeModules(raw.modules)
|
|
500
|
+
const moduleIds = new Set(modules?.map((item) => item.id) ?? [])
|
|
501
|
+
for (const block of blocks) {
|
|
502
|
+
if (block.moduleId && !moduleIds.has(block.moduleId)) block.moduleId = undefined
|
|
503
|
+
}
|
|
451
504
|
return syncFormDefinition({
|
|
452
505
|
title: typeof raw.title === 'string' ? raw.title : '',
|
|
453
506
|
description: typeof raw.description === 'string' ? raw.description : '',
|
|
507
|
+
modules,
|
|
454
508
|
blocks,
|
|
455
509
|
jsonSchema: {},
|
|
456
510
|
})
|
|
@@ -26,6 +26,7 @@ export function resolveSurfaceFromFormDefinition(
|
|
|
26
26
|
const normalized = normalizeFormDefinition({
|
|
27
27
|
title: typeof payload.title === 'string' ? payload.title : '',
|
|
28
28
|
description: typeof payload.description === 'string' ? payload.description : '',
|
|
29
|
+
modules: Array.isArray(payload.modules) ? payload.modules : undefined,
|
|
29
30
|
blocks,
|
|
30
31
|
jsonSchema: normalizeJsonSchema(payload.jsonSchema ?? payload.json_schema),
|
|
31
32
|
})
|
|
@@ -34,7 +35,7 @@ export function resolveSurfaceFromFormDefinition(
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export function buildAskUserSurface(
|
|
37
|
-
formDef: Pick<FormSchema, 'title' | 'description'>,
|
|
38
|
+
formDef: Pick<FormSchema, 'title' | 'description' | 'modules'>,
|
|
38
39
|
matchedBlocks: FormBlock[],
|
|
39
40
|
options?: BlocksToA2uiOptions,
|
|
40
41
|
): A2uiSurfaceDoc {
|
|
@@ -42,6 +43,7 @@ export function buildAskUserSurface(
|
|
|
42
43
|
{
|
|
43
44
|
title: formDef.title,
|
|
44
45
|
description: formDef.description,
|
|
46
|
+
modules: formDef.modules,
|
|
45
47
|
blocks: matchedBlocks,
|
|
46
48
|
},
|
|
47
49
|
options,
|
|
@@ -60,6 +62,7 @@ export function mapFormDefinitionFromDto(raw: unknown): FormSchema | undefined {
|
|
|
60
62
|
return normalizeFormDefinition({
|
|
61
63
|
title: typeof obj.title === 'string' ? obj.title : '',
|
|
62
64
|
description: typeof obj.description === 'string' ? obj.description : '',
|
|
65
|
+
modules: Array.isArray(obj.modules) ? obj.modules as FormSchema['modules'] : undefined,
|
|
63
66
|
blocks: Array.isArray(obj.blocks) ? (obj.blocks as FormSchema['blocks']) : [],
|
|
64
67
|
jsonSchema: normalizeJsonSchema(obj.jsonSchema ?? obj.json_schema),
|
|
65
68
|
})
|