@skopon-cool/form-sdk 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/a2uiAdapter.d.ts.map +1 -1
- package/dist/adapter/formSchema.d.ts.map +1 -1
- package/dist/blocks/{case_singleselect → case_multiselect}/adapter.d.ts +2 -2
- package/dist/blocks/case_multiselect/adapter.d.ts.map +1 -0
- package/dist/blocks/case_multiselect/index.d.ts +3 -0
- package/dist/blocks/case_multiselect/index.d.ts.map +1 -0
- package/dist/catalog/resumeSearchContext.d.ts +9 -0
- package/dist/catalog/resumeSearchContext.d.ts.map +1 -1
- package/dist/catalog/skoponCaseSelect.d.ts.map +1 -1
- package/dist/catalog/skoponResumeSelect.d.ts.map +1 -1
- package/dist/components/AskUserFormCard.d.ts.map +1 -1
- package/dist/components/CurlSubmitBlock.d.ts +4 -1
- package/dist/components/CurlSubmitBlock.d.ts.map +1 -1
- package/dist/components/SkoponA2uiStreamRenderer.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 +901 -852
- package/dist/submit/buildCurlStatement.d.ts +3 -1
- package/dist/submit/buildCurlStatement.d.ts.map +1 -1
- package/dist/submit/intersectPayloadBlocksWithForm.d.ts.map +1 -1
- package/dist/types/index.d.ts +11 -4
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapter/a2uiAdapter.test.ts +37 -14
- package/src/adapter/a2uiAdapter.ts +1 -4
- package/src/adapter/formSchema.ts +49 -29
- package/src/blocks/case_multiselect/adapter.ts +90 -0
- package/src/blocks/case_multiselect/index.ts +14 -0
- package/src/blocks/registry.ts +2 -2
- package/src/catalog/resumeSearchContext.tsx +10 -0
- package/src/catalog/skoponCaseSelect.tsx +38 -13
- package/src/catalog/skoponResumeSelect.tsx +76 -10
- package/src/components/AskUserFormCard.tsx +3 -1
- package/src/components/CurlSubmitBlock.tsx +28 -7
- package/src/components/SkoponA2uiStreamRenderer.tsx +11 -4
- package/src/index.ts +6 -1
- package/src/styles/a2ui-preview.css +4 -4
- package/src/styles/index.css +148 -17
- package/src/submit/buildCurlStatement.ts +18 -23
- package/src/submit/intersectPayloadBlocksWithForm.ts +14 -2
- package/src/submit/submit.test.ts +66 -3
- package/src/types/index.ts +10 -3
- package/dist/blocks/case_singleselect/adapter.d.ts.map +0 -1
- package/dist/blocks/case_singleselect/index.d.ts +0 -3
- package/dist/blocks/case_singleselect/index.d.ts.map +0 -1
- package/src/blocks/case_singleselect/adapter.ts +0 -74
- package/src/blocks/case_singleselect/index.ts +0 -14
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function buildCurlStatement(payload: unknown, callbackUrl?: string | null): string;
|
|
2
|
-
/**
|
|
2
|
+
/** 构建合法 JSON body(card + extra 合并,便于 curl 直接执行) */
|
|
3
3
|
export declare function buildAskUserCurlBodyJson(cardValues: Record<string, unknown>, extraValues: Record<string, unknown>): string;
|
|
4
4
|
export interface BuildAskUserCurlStatementOptions {
|
|
5
5
|
cardValues: Record<string, unknown>;
|
|
@@ -7,4 +7,6 @@ export interface BuildAskUserCurlStatementOptions {
|
|
|
7
7
|
callbackUrl?: string | null;
|
|
8
8
|
}
|
|
9
9
|
export declare function buildAskUserCurlStatement({ cardValues, extraValues, callbackUrl, }: BuildAskUserCurlStatementOptions): string;
|
|
10
|
+
/** 从 ask_user payload(blocksJson)生成向 callback 提交返回字段的 curl */
|
|
11
|
+
export declare function buildAskUserSubmitCurlFromPayload(payload: unknown, callbackUrl?: string | null): string;
|
|
10
12
|
//# sourceMappingURL=buildCurlStatement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildCurlStatement.d.ts","sourceRoot":"","sources":["../../src/submit/buildCurlStatement.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildCurlStatement.d.ts","sourceRoot":"","sources":["../../src/submit/buildCurlStatement.ts"],"names":[],"mappings":"AASA,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQxF;AAED,mDAAmD;AACnD,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAER;AAED,MAAM,WAAW,gCAAgC;IAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAgB,yBAAyB,CAAC,EACxC,UAAU,EACV,WAAgB,EAChB,WAAW,GACZ,EAAE,gCAAgC,GAAG,MAAM,CAQ3C;AAED,8DAA8D;AAC9D,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,OAAO,EAChB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,MAAM,CAKR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AACA,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,CAAA;AAE1F,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,0DAA0D;IAC1D,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAqDD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAUvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,uBAAuB,EACnC,cAAc,EAAE,UAAU,GAAG,SAAS,GACrC,yBAAyB,CAqC3B;
|
|
1
|
+
{"version":3,"file":"intersectPayloadBlocksWithForm.d.ts","sourceRoot":"","sources":["../../src/submit/intersectPayloadBlocksWithForm.ts"],"names":[],"mappings":"AACA,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,CAAA;AAE1F,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,SAAS,EAAE,CAAA;IAC1B,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,0DAA0D;IAC1D,YAAY,EAAE,SAAS,EAAE,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAqDD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAUvF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,uBAAuB,EACnC,cAAc,EAAE,UAAU,GAAG,SAAS,GACrC,yBAAyB,CAqC3B;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,CAIlF;AAED,0DAA0D;AAC1D,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,uBAAuB,GAAG,SAAS,EAAE,CAK3F;AAED,mDAAmD;AACnD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,EAAE,CAIvF"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,7 +21,9 @@ export interface A2uiSurfaceDoc {
|
|
|
21
21
|
}
|
|
22
22
|
export declare const A2UI_PROTOCOL_VERSION: "v0.9";
|
|
23
23
|
export type FormJsonSchema = Record<string, unknown>;
|
|
24
|
-
export type FormBlockType = 'heading' | 'paragraph' | 'text' | 'textarea' | 'email' | 'number' | 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle' | 'tel' | 'url' | 'datetime' | 'time' | 'file' | 'resume_multiselect' | '
|
|
24
|
+
export type FormBlockType = 'heading' | 'paragraph' | 'text' | 'textarea' | 'email' | 'number' | 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle' | 'tel' | 'url' | 'datetime' | 'time' | 'file' | 'resume_multiselect' | 'case_multiselect'
|
|
25
|
+
/** @deprecated 加载时自动迁移为 case_multiselect */
|
|
26
|
+
| 'case_singleselect' | 'image' | 'video' | 'audio';
|
|
25
27
|
export type FormMediaSize = 'huge' | 'large' | 'medium' | 'small' | 'icon';
|
|
26
28
|
export type FormFilePlaceholderIcon = 'video' | 'audio' | 'image' | 'file' | 'spreadsheet' | 'document';
|
|
27
29
|
export declare const FORM_MEDIA_SIZES: FormMediaSize[];
|
|
@@ -36,13 +38,18 @@ export interface FormResumeFilter {
|
|
|
36
38
|
resumeUniqueIds?: string[];
|
|
37
39
|
pageSize?: number;
|
|
38
40
|
}
|
|
39
|
-
/**
|
|
41
|
+
/** 案例多选组件:渲染时用于 /univ/case/list 的筛选条件 */
|
|
40
42
|
export interface FormCaseFilter {
|
|
41
43
|
/** Agent 类型(编辑器辅助,运行时不用) */
|
|
42
44
|
agentKind?: string;
|
|
43
|
-
/** Agent unique_id
|
|
45
|
+
/** Agent unique_id(运行时用于限定所属 Agent) */
|
|
44
46
|
agentUniqueId?: string;
|
|
45
|
-
|
|
47
|
+
/** 流类型 unique_id */
|
|
48
|
+
flowType?: string;
|
|
49
|
+
/** 流类别 unique_id */
|
|
50
|
+
category?: string;
|
|
51
|
+
/** 流程编号(flow_unique_id)多选 */
|
|
52
|
+
flowUniqueIds?: string[];
|
|
46
53
|
pageSize?: number;
|
|
47
54
|
}
|
|
48
55
|
export interface FormBlock {
|
|
@@ -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,cAAc,GACd,oBAAoB,GACpB,kBAAkB,CAAA;AAEtB,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,iBAAiB,GAAG,MAAM,CAAA;IACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,iBAAiB,EAAE,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CAC1E;AAED,eAAO,MAAM,qBAAqB,EAAG,MAAe,CAAA;AAEpD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEpD,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,WAAW,GACX,MAAM,GACN,UAAU,GACV,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,OAAO,GACP,UAAU,GACV,QAAQ,GACR,KAAK,GACL,KAAK,GACL,UAAU,GACV,MAAM,GACN,MAAM,GACN,oBAAoB,GACpB,mBAAmB,GACnB,OAAO,GACP,OAAO,GACP,OAAO,CAAA;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;AAE1E,MAAM,MAAM,uBAAuB,GAC/B,OAAO,GACP,OAAO,GACP,OAAO,GACP,MAAM,GACN,aAAa,GACb,UAAU,CAAA;AAEd,eAAO,MAAM,gBAAgB,EAAE,aAAa,EAM3C,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,yCAAyC;AACzC,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { describe, it, expect } from 'vitest'
|
|
5
5
|
import type { FormSchema } from '../types/index'
|
|
6
6
|
import { a2uiToBlocks, blocksToA2ui, isA2uiSurfaceEmpty, surfaceDocToMessages } from './a2uiAdapter'
|
|
7
|
+
import { normalizeFormDefinition } from './formSchema'
|
|
7
8
|
|
|
8
9
|
function makeDefinition(): Pick<FormSchema, 'title' | 'description' | 'blocks'> {
|
|
9
10
|
return {
|
|
@@ -239,7 +240,7 @@ describe('a2uiAdapter blocks <-> surface', () => {
|
|
|
239
240
|
expect((withHeader.components.find((c) => c.id === 'root')?.children as string[]).length).toBe(12)
|
|
240
241
|
})
|
|
241
242
|
|
|
242
|
-
it('round-trips
|
|
243
|
+
it('round-trips case_multiselect through blocksToA2ui and a2uiToBlocks', () => {
|
|
243
244
|
const doc = blocksToA2ui(
|
|
244
245
|
{
|
|
245
246
|
title: '',
|
|
@@ -247,19 +248,21 @@ describe('a2uiAdapter blocks <-> surface', () => {
|
|
|
247
248
|
blocks: [
|
|
248
249
|
{
|
|
249
250
|
id: 'b-case',
|
|
250
|
-
type: '
|
|
251
|
-
name: '
|
|
251
|
+
type: 'case_multiselect',
|
|
252
|
+
name: 'selected_cases',
|
|
252
253
|
label: '选择案例',
|
|
253
254
|
placeholder: '暂无案例',
|
|
254
|
-
help: '
|
|
255
|
+
help: '请选择一个或多个案例',
|
|
255
256
|
caseEnableRefresh: true,
|
|
256
257
|
caseFilter: {
|
|
257
258
|
agentKind: 'public-user',
|
|
258
259
|
agentUniqueId: 'agent-1',
|
|
259
|
-
|
|
260
|
+
flowType: 'content',
|
|
261
|
+
category: 'short-video',
|
|
262
|
+
flowUniqueIds: ['flow-rec-a', 'flow-rec-b'],
|
|
260
263
|
pageSize: 10,
|
|
261
264
|
},
|
|
262
|
-
defaultValue: 'case-abc',
|
|
265
|
+
defaultValue: ['case-abc', 'case-def'],
|
|
263
266
|
},
|
|
264
267
|
],
|
|
265
268
|
},
|
|
@@ -271,19 +274,39 @@ describe('a2uiAdapter blocks <-> surface', () => {
|
|
|
271
274
|
expect(node?.caseFilter).toEqual({
|
|
272
275
|
agentKind: 'public-user',
|
|
273
276
|
agentUniqueId: 'agent-1',
|
|
274
|
-
|
|
277
|
+
flowType: 'content',
|
|
278
|
+
category: 'short-video',
|
|
279
|
+
flowUniqueIds: ['flow-rec-a', 'flow-rec-b'],
|
|
275
280
|
pageSize: 10,
|
|
276
281
|
})
|
|
277
|
-
expect(doc.dataModel?.
|
|
282
|
+
expect(doc.dataModel?.selected_cases).toEqual(['case-abc', 'case-def'])
|
|
278
283
|
|
|
279
284
|
const back = a2uiToBlocks(doc)
|
|
280
|
-
const block = back.blocks.find((b) => b.name === '
|
|
281
|
-
expect(block?.type).toBe('
|
|
285
|
+
const block = back.blocks.find((b) => b.name === 'selected_cases')
|
|
286
|
+
expect(block?.type).toBe('case_multiselect')
|
|
282
287
|
expect(block?.caseEnableRefresh).toBe(true)
|
|
283
|
-
expect(block?.caseFilter?.
|
|
288
|
+
expect(block?.caseFilter?.flowType).toBe('content')
|
|
289
|
+
expect(block?.caseFilter?.category).toBe('short-video')
|
|
290
|
+
expect(block?.caseFilter?.flowUniqueIds).toEqual(['flow-rec-a', 'flow-rec-b'])
|
|
284
291
|
expect(block?.caseFilter?.pageSize).toBe(10)
|
|
285
|
-
expect(block?.
|
|
286
|
-
|
|
287
|
-
|
|
292
|
+
expect(block?.defaultValue).toEqual(['case-abc', 'case-def'])
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('migrates legacy case_singleselect to case_multiselect on normalize', () => {
|
|
296
|
+
const normalized = normalizeFormDefinition({
|
|
297
|
+
title: '',
|
|
298
|
+
description: '',
|
|
299
|
+
blocks: [
|
|
300
|
+
{
|
|
301
|
+
id: 'legacy',
|
|
302
|
+
type: 'case_singleselect',
|
|
303
|
+
name: 'old_case',
|
|
304
|
+
defaultValue: 'case-old',
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
jsonSchema: {},
|
|
308
|
+
})
|
|
309
|
+
expect(normalized.blocks[0]?.type).toBe('case_multiselect')
|
|
310
|
+
expect(normalized.blocks[0]?.defaultValue).toEqual(['case-old'])
|
|
288
311
|
})
|
|
289
312
|
})
|
|
@@ -101,15 +101,12 @@ function defaultValueForBlock(block: FormBlock): unknown {
|
|
|
101
101
|
case 'multiselect':
|
|
102
102
|
case 'checkbox':
|
|
103
103
|
case 'resume_multiselect':
|
|
104
|
+
case 'case_multiselect':
|
|
104
105
|
if (Array.isArray(block.defaultValue)) return block.defaultValue
|
|
105
106
|
if (typeof block.defaultValue === 'string' && block.defaultValue) return [block.defaultValue]
|
|
106
107
|
return []
|
|
107
108
|
case 'select':
|
|
108
109
|
case 'radio':
|
|
109
|
-
case 'case_singleselect':
|
|
110
|
-
if (Array.isArray(block.defaultValue)) return block.defaultValue[0] ?? ''
|
|
111
|
-
if (typeof block.defaultValue === 'string') return block.defaultValue
|
|
112
|
-
return ''
|
|
113
110
|
case 'number':
|
|
114
111
|
if (typeof block.defaultValue === 'number') return block.defaultValue
|
|
115
112
|
if (typeof block.defaultValue === 'string' && block.defaultValue) return block.defaultValue
|
|
@@ -29,7 +29,7 @@ function normalizeDefaultValue(
|
|
|
29
29
|
): FormBlock['defaultValue'] {
|
|
30
30
|
if (raw === undefined) return undefined
|
|
31
31
|
if (type === 'toggle') return coerceToggleValue(raw)
|
|
32
|
-
if (type === 'multiselect' || type === 'checkbox' || type === 'resume_multiselect') {
|
|
32
|
+
if (type === 'multiselect' || type === 'checkbox' || type === 'resume_multiselect' || type === 'case_multiselect') {
|
|
33
33
|
if (Array.isArray(raw)) return raw.map(String)
|
|
34
34
|
if (typeof raw === 'string' && raw) return [raw]
|
|
35
35
|
return []
|
|
@@ -45,9 +45,6 @@ function normalizeCaseFilter(raw: FormCaseFilter | undefined): FormCaseFilter {
|
|
|
45
45
|
Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
|
|
46
46
|
? Math.floor(pageSizeRaw)
|
|
47
47
|
: 20
|
|
48
|
-
const flowIdRaw = typeof raw?.flowId === 'number' ? raw.flowId : Number(raw?.flowId)
|
|
49
|
-
const flowId =
|
|
50
|
-
Number.isFinite(flowIdRaw) && flowIdRaw > 0 ? Math.floor(flowIdRaw) : undefined
|
|
51
48
|
const agentKind =
|
|
52
49
|
typeof raw?.agentKind === 'string' && raw.agentKind.trim()
|
|
53
50
|
? raw.agentKind.trim()
|
|
@@ -56,7 +53,18 @@ function normalizeCaseFilter(raw: FormCaseFilter | undefined): FormCaseFilter {
|
|
|
56
53
|
typeof raw?.agentUniqueId === 'string' && raw.agentUniqueId.trim()
|
|
57
54
|
? raw.agentUniqueId.trim()
|
|
58
55
|
: undefined
|
|
59
|
-
|
|
56
|
+
const flowType =
|
|
57
|
+
typeof raw?.flowType === 'string' && raw.flowType.trim()
|
|
58
|
+
? raw.flowType.trim()
|
|
59
|
+
: undefined
|
|
60
|
+
const category =
|
|
61
|
+
typeof raw?.category === 'string' && raw.category.trim()
|
|
62
|
+
? raw.category.trim()
|
|
63
|
+
: undefined
|
|
64
|
+
const flowUniqueIds = Array.isArray(raw?.flowUniqueIds)
|
|
65
|
+
? raw.flowUniqueIds.map(String).filter(Boolean)
|
|
66
|
+
: []
|
|
67
|
+
return { agentKind, agentUniqueId, flowType, category, flowUniqueIds, pageSize }
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
function normalizeResumeFilter(raw: FormResumeFilter | undefined): FormResumeFilter {
|
|
@@ -77,44 +85,56 @@ function normalizeResumeFilter(raw: FormResumeFilter | undefined): FormResumeFil
|
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
|
|
88
|
+
function migrateLegacyBlock(raw: FormBlock): FormBlock {
|
|
89
|
+
if (raw.type !== 'case_singleselect') return raw
|
|
90
|
+
const defaultValue =
|
|
91
|
+
typeof raw.defaultValue === 'string' && raw.defaultValue.trim()
|
|
92
|
+
? [raw.defaultValue.trim()]
|
|
93
|
+
: Array.isArray(raw.defaultValue)
|
|
94
|
+
? raw.defaultValue.map(String).filter(Boolean)
|
|
95
|
+
: []
|
|
96
|
+
return { ...raw, type: 'case_multiselect', defaultValue }
|
|
97
|
+
}
|
|
98
|
+
|
|
80
99
|
function normalizeBlock(raw: FormBlock): FormBlock {
|
|
81
|
-
const
|
|
82
|
-
const
|
|
100
|
+
const migrated = migrateLegacyBlock(raw)
|
|
101
|
+
const fileAcceptTypes = normalizeFileAcceptTypes(migrated.fileAcceptTypes)
|
|
102
|
+
const type = migrated.type
|
|
83
103
|
return {
|
|
84
|
-
id:
|
|
104
|
+
id: migrated.id?.trim() || generateId('block-'),
|
|
85
105
|
type,
|
|
86
|
-
name:
|
|
87
|
-
label:
|
|
88
|
-
placeholder:
|
|
89
|
-
help:
|
|
90
|
-
required:
|
|
106
|
+
name: migrated.name?.trim() || undefined,
|
|
107
|
+
label: migrated.label ?? '',
|
|
108
|
+
placeholder: migrated.placeholder ?? '',
|
|
109
|
+
help: migrated.help ?? '',
|
|
110
|
+
required: migrated.required === true,
|
|
91
111
|
mediaUrls: isMediaBlockType(type)
|
|
92
|
-
? normalizeMediaUrls(
|
|
112
|
+
? normalizeMediaUrls(migrated, DEFAULT_MEDIA_URL_MAX)
|
|
93
113
|
: undefined,
|
|
94
|
-
mediaSize: isMediaBlockType(type) ? normalizeMediaSize(
|
|
114
|
+
mediaSize: isMediaBlockType(type) ? normalizeMediaSize(migrated.mediaSize) : undefined,
|
|
95
115
|
fileAcceptTypes,
|
|
96
116
|
fileAcceptExtensions: filterFileAcceptExtensionsForTypes(
|
|
97
117
|
fileAcceptTypes,
|
|
98
|
-
|
|
118
|
+
migrated.fileAcceptExtensions,
|
|
99
119
|
),
|
|
100
|
-
filePlaceholderIcon: normalizeFilePlaceholderIcon(
|
|
101
|
-
fileMinCount: type === 'file' ? normalizeFileUploadCount(
|
|
102
|
-
fileMaxCount: type === 'file' ? normalizeFileUploadCount(
|
|
103
|
-
defaultValue: normalizeDefaultValue(type,
|
|
104
|
-
options: Array.isArray(
|
|
105
|
-
?
|
|
120
|
+
filePlaceholderIcon: normalizeFilePlaceholderIcon(migrated.filePlaceholderIcon),
|
|
121
|
+
fileMinCount: type === 'file' ? normalizeFileUploadCount(migrated.fileMinCount, 1) : undefined,
|
|
122
|
+
fileMaxCount: type === 'file' ? normalizeFileUploadCount(migrated.fileMaxCount, 1) : undefined,
|
|
123
|
+
defaultValue: normalizeDefaultValue(type, migrated.defaultValue),
|
|
124
|
+
options: Array.isArray(migrated.options)
|
|
125
|
+
? migrated.options.map((opt, index) => ({
|
|
106
126
|
value: opt.value?.trim() || `option_${index + 1}`,
|
|
107
127
|
label: opt.label?.trim() || `选项 ${index + 1}`,
|
|
108
128
|
}))
|
|
109
129
|
: undefined,
|
|
110
130
|
resumeEnableRefresh:
|
|
111
|
-
type === 'resume_multiselect' ?
|
|
131
|
+
type === 'resume_multiselect' ? migrated.resumeEnableRefresh !== false : undefined,
|
|
112
132
|
resumeFilter:
|
|
113
|
-
type === 'resume_multiselect' ? normalizeResumeFilter(
|
|
133
|
+
type === 'resume_multiselect' ? normalizeResumeFilter(migrated.resumeFilter) : undefined,
|
|
114
134
|
caseEnableRefresh:
|
|
115
|
-
type === '
|
|
135
|
+
type === 'case_multiselect' ? migrated.caseEnableRefresh !== false : undefined,
|
|
116
136
|
caseFilter:
|
|
117
|
-
type === '
|
|
137
|
+
type === 'case_multiselect' ? normalizeCaseFilter(migrated.caseFilter) : undefined,
|
|
118
138
|
}
|
|
119
139
|
}
|
|
120
140
|
|
|
@@ -192,10 +212,10 @@ export function createEmptyBlock(type: FormBlockType): FormBlock {
|
|
|
192
212
|
block.defaultValue = []
|
|
193
213
|
}
|
|
194
214
|
|
|
195
|
-
if (type === '
|
|
215
|
+
if (type === 'case_multiselect') {
|
|
196
216
|
block.caseEnableRefresh = true
|
|
197
|
-
block.caseFilter = { pageSize: 20 }
|
|
198
|
-
block.defaultValue =
|
|
217
|
+
block.caseFilter = { flowUniqueIds: [], pageSize: 20 }
|
|
218
|
+
block.defaultValue = []
|
|
199
219
|
}
|
|
200
220
|
|
|
201
221
|
return block
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { A2uiComponentNode, FormBlock } from '../../types/index'
|
|
2
|
+
import type { BlockAdapterContext, BlockToComponentResult } from '../types'
|
|
3
|
+
|
|
4
|
+
function asLiteral(value: unknown): string | undefined {
|
|
5
|
+
return typeof value === 'string' ? value : undefined
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function readCaseFilterFromNode(cf: Record<string, unknown>) {
|
|
9
|
+
const pageSizeRaw = typeof cf.pageSize === 'number' ? cf.pageSize : Number(cf.pageSize)
|
|
10
|
+
const agentKind =
|
|
11
|
+
typeof cf.agentKind === 'string' && cf.agentKind.trim()
|
|
12
|
+
? cf.agentKind.trim()
|
|
13
|
+
: undefined
|
|
14
|
+
const agentUniqueId =
|
|
15
|
+
typeof cf.agentUniqueId === 'string' && cf.agentUniqueId.trim()
|
|
16
|
+
? cf.agentUniqueId.trim()
|
|
17
|
+
: undefined
|
|
18
|
+
const flowType =
|
|
19
|
+
typeof cf.flowType === 'string' && cf.flowType.trim()
|
|
20
|
+
? cf.flowType.trim()
|
|
21
|
+
: undefined
|
|
22
|
+
const category =
|
|
23
|
+
typeof cf.category === 'string' && cf.category.trim()
|
|
24
|
+
? cf.category.trim()
|
|
25
|
+
: undefined
|
|
26
|
+
const flowUniqueIds = Array.isArray(cf.flowUniqueIds)
|
|
27
|
+
? cf.flowUniqueIds.map(String).filter(Boolean)
|
|
28
|
+
: []
|
|
29
|
+
return {
|
|
30
|
+
agentKind,
|
|
31
|
+
agentUniqueId,
|
|
32
|
+
flowType,
|
|
33
|
+
category,
|
|
34
|
+
flowUniqueIds,
|
|
35
|
+
pageSize:
|
|
36
|
+
Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
|
|
37
|
+
? Math.floor(pageSizeRaw)
|
|
38
|
+
: 20,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function caseMultiselectToComponent(
|
|
43
|
+
block: FormBlock,
|
|
44
|
+
ctx: BlockAdapterContext,
|
|
45
|
+
): BlockToComponentResult {
|
|
46
|
+
const { id, label, path, withData } = ctx
|
|
47
|
+
return withData({
|
|
48
|
+
id,
|
|
49
|
+
component: 'SkoponCaseSelect',
|
|
50
|
+
label,
|
|
51
|
+
placeholder: block.placeholder ?? '',
|
|
52
|
+
help: block.help ?? '',
|
|
53
|
+
enableRefresh: block.caseEnableRefresh !== false,
|
|
54
|
+
caseFilter: {
|
|
55
|
+
agentKind: block.caseFilter?.agentKind,
|
|
56
|
+
agentUniqueId: block.caseFilter?.agentUniqueId,
|
|
57
|
+
flowType: block.caseFilter?.flowType,
|
|
58
|
+
category: block.caseFilter?.category,
|
|
59
|
+
flowUniqueIds: block.caseFilter?.flowUniqueIds ?? [],
|
|
60
|
+
pageSize: block.caseFilter?.pageSize ?? 20,
|
|
61
|
+
},
|
|
62
|
+
value: { path },
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function caseMultiselectFromComponent(
|
|
67
|
+
node: A2uiComponentNode,
|
|
68
|
+
base: (type: 'case_multiselect') => FormBlock,
|
|
69
|
+
helpers: {
|
|
70
|
+
asLiteral: (value: unknown) => string | undefined
|
|
71
|
+
nameFromValue: (value: unknown) => string
|
|
72
|
+
},
|
|
73
|
+
): FormBlock {
|
|
74
|
+
const name = helpers.nameFromValue(node.value)
|
|
75
|
+
const block: FormBlock = {
|
|
76
|
+
...base('case_multiselect'),
|
|
77
|
+
name,
|
|
78
|
+
caseEnableRefresh: node.enableRefresh !== false,
|
|
79
|
+
}
|
|
80
|
+
const placeholder = helpers.asLiteral(node.placeholder)
|
|
81
|
+
if (placeholder) block.placeholder = placeholder
|
|
82
|
+
const help = helpers.asLiteral(node.help)
|
|
83
|
+
if (help) block.help = help
|
|
84
|
+
if (node.caseFilter && typeof node.caseFilter === 'object') {
|
|
85
|
+
block.caseFilter = readCaseFilterFromNode(node.caseFilter as Record<string, unknown>)
|
|
86
|
+
}
|
|
87
|
+
return block
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { asLiteral }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BlockAdapterPlugin } from '../types'
|
|
2
|
+
import {
|
|
3
|
+
caseMultiselectFromComponent,
|
|
4
|
+
caseMultiselectToComponent,
|
|
5
|
+
} from './adapter'
|
|
6
|
+
import { SkoponCaseSelectImpl } from '../../catalog/skoponCaseSelect'
|
|
7
|
+
|
|
8
|
+
export const caseMultiselectAdapter: BlockAdapterPlugin = {
|
|
9
|
+
type: 'case_multiselect',
|
|
10
|
+
componentName: 'SkoponCaseSelect',
|
|
11
|
+
toComponent: caseMultiselectToComponent,
|
|
12
|
+
fromComponent: caseMultiselectFromComponent,
|
|
13
|
+
catalogComponents: [SkoponCaseSelectImpl],
|
|
14
|
+
}
|
package/src/blocks/registry.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { FormBlockType } from '../types/index'
|
|
2
2
|
import type { BlockAdapterPlugin } from './types'
|
|
3
|
-
import {
|
|
3
|
+
import { caseMultiselectAdapter } from './case_multiselect'
|
|
4
4
|
import { resumeMultiselectAdapter } from './resume_multiselect'
|
|
5
5
|
|
|
6
|
-
const adapters: BlockAdapterPlugin[] = [resumeMultiselectAdapter,
|
|
6
|
+
const adapters: BlockAdapterPlugin[] = [resumeMultiselectAdapter, caseMultiselectAdapter]
|
|
7
7
|
|
|
8
8
|
const adapterByType = new Map<FormBlockType, BlockAdapterPlugin>(
|
|
9
9
|
adapters.map((adapter) => [adapter.type, adapter]),
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { createContext, useContext, type ReactNode } from 'react'
|
|
2
2
|
import type { FormResumeFilter } from '../types/index'
|
|
3
3
|
|
|
4
|
+
export interface ResumeSearchWorkItem {
|
|
5
|
+
title: string
|
|
6
|
+
coverUrl?: string | null
|
|
7
|
+
link?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
export interface ResumeSearchItem {
|
|
5
11
|
resumeUniqueId: string
|
|
6
12
|
resumeId?: number
|
|
@@ -11,6 +17,10 @@ export interface ResumeSearchItem {
|
|
|
11
17
|
satisfaction?: number
|
|
12
18
|
published?: number
|
|
13
19
|
worksCount?: number
|
|
20
|
+
personality?: string[]
|
|
21
|
+
specialties?: string[]
|
|
22
|
+
traits?: string[]
|
|
23
|
+
works?: ResumeSearchWorkItem[]
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
export interface ResumeSearchParams {
|
|
@@ -6,7 +6,7 @@ import { createBinderlessComponentImplementation } from '@a2ui/react/v0_9'
|
|
|
6
6
|
import { z } from 'zod'
|
|
7
7
|
import type { FormCaseFilter } from '../types/index'
|
|
8
8
|
import { useA2uiPreviewMode } from './a2uiPreviewContext'
|
|
9
|
-
import {
|
|
9
|
+
import { asStringArray, useSkoponBoundField } from './useSkoponBoundField'
|
|
10
10
|
import { type CaseSearchItem, useCaseSearch } from './caseSearchContext'
|
|
11
11
|
|
|
12
12
|
function readString(value: unknown): string {
|
|
@@ -15,18 +15,40 @@ function readString(value: unknown): string {
|
|
|
15
15
|
|
|
16
16
|
function readCaseFilter(raw: unknown): FormCaseFilter {
|
|
17
17
|
if (!raw || typeof raw !== 'object') {
|
|
18
|
-
return { pageSize: 20 }
|
|
18
|
+
return { flowUniqueIds: [], pageSize: 20 }
|
|
19
19
|
}
|
|
20
20
|
const rec = raw as Record<string, unknown>
|
|
21
|
-
const flowIdRaw = typeof rec.flowId === 'number' ? rec.flowId : Number(rec.flowId)
|
|
22
|
-
const flowId =
|
|
23
|
-
Number.isFinite(flowIdRaw) && flowIdRaw > 0 ? Math.floor(flowIdRaw) : undefined
|
|
24
21
|
const pageSizeRaw = typeof rec.pageSize === 'number' ? rec.pageSize : Number(rec.pageSize)
|
|
25
22
|
const pageSize =
|
|
26
23
|
Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
|
|
27
24
|
? Math.floor(pageSizeRaw)
|
|
28
25
|
: 20
|
|
29
|
-
|
|
26
|
+
const agentKind =
|
|
27
|
+
typeof rec.agentKind === 'string' && rec.agentKind.trim()
|
|
28
|
+
? rec.agentKind.trim()
|
|
29
|
+
: undefined
|
|
30
|
+
const agentUniqueId =
|
|
31
|
+
typeof rec.agentUniqueId === 'string' && rec.agentUniqueId.trim()
|
|
32
|
+
? rec.agentUniqueId.trim()
|
|
33
|
+
: undefined
|
|
34
|
+
const flowType =
|
|
35
|
+
typeof rec.flowType === 'string' && rec.flowType.trim()
|
|
36
|
+
? rec.flowType.trim()
|
|
37
|
+
: undefined
|
|
38
|
+
const category =
|
|
39
|
+
typeof rec.category === 'string' && rec.category.trim()
|
|
40
|
+
? rec.category.trim()
|
|
41
|
+
: undefined
|
|
42
|
+
const flowUniqueIds = Array.isArray(rec.flowUniqueIds)
|
|
43
|
+
? rec.flowUniqueIds.map(String).filter(Boolean)
|
|
44
|
+
: []
|
|
45
|
+
return { agentKind, agentUniqueId, flowType, category, flowUniqueIds, pageSize }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isCaseFilterReady(filter: FormCaseFilter): boolean {
|
|
49
|
+
const hasFlowIds = Boolean(filter.flowUniqueIds?.length)
|
|
50
|
+
const hasCategory = Boolean(filter.agentUniqueId && filter.flowType && filter.category)
|
|
51
|
+
return hasFlowIds || hasCategory
|
|
30
52
|
}
|
|
31
53
|
|
|
32
54
|
function filterKey(filter: FormCaseFilter): string {
|
|
@@ -104,20 +126,20 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
104
126
|
const [pageSize, setPageSize] = useState(caseFilter.pageSize ?? 20)
|
|
105
127
|
const requestSeqRef = useRef(0)
|
|
106
128
|
|
|
107
|
-
const
|
|
129
|
+
const selectedIds = asStringArray(value)
|
|
108
130
|
|
|
109
131
|
const emptyHint = useMemo(() => {
|
|
110
132
|
if (!caseSearch) return '未配置案例搜索服务'
|
|
111
|
-
if (!caseFilter
|
|
133
|
+
if (!isCaseFilterReady(caseFilter)) return '未配置案例列表筛选条件'
|
|
112
134
|
if (fetchError) return fetchError
|
|
113
135
|
return placeholder || '暂无匹配的案例'
|
|
114
|
-
}, [caseSearch, caseFilter
|
|
136
|
+
}, [caseSearch, caseFilter, fetchError, placeholder])
|
|
115
137
|
|
|
116
138
|
const fetchPage = useCallback(
|
|
117
139
|
async (targetPage: number) => {
|
|
118
140
|
const filter = readCaseFilter(JSON.parse(filterSig) as FormCaseFilter)
|
|
119
141
|
const seq = ++requestSeqRef.current
|
|
120
|
-
if (!caseSearch || !filter
|
|
142
|
+
if (!caseSearch || !isCaseFilterReady(filter)) {
|
|
121
143
|
setItems([])
|
|
122
144
|
setTotal(0)
|
|
123
145
|
setFetchError('')
|
|
@@ -151,7 +173,10 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
151
173
|
|
|
152
174
|
const toggleSelect = (caseUniqueId: string) => {
|
|
153
175
|
if (!interactive) return
|
|
154
|
-
|
|
176
|
+
const next = selectedIds.includes(caseUniqueId)
|
|
177
|
+
? selectedIds.filter((id) => id !== caseUniqueId)
|
|
178
|
+
: [...selectedIds, caseUniqueId]
|
|
179
|
+
setValue(next)
|
|
155
180
|
}
|
|
156
181
|
|
|
157
182
|
const handleRefresh = () => {
|
|
@@ -179,14 +204,14 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
179
204
|
<CaseCard
|
|
180
205
|
key={item.caseUniqueId}
|
|
181
206
|
item={item}
|
|
182
|
-
selected={
|
|
207
|
+
selected={selectedIds.includes(item.caseUniqueId)}
|
|
183
208
|
disabled={!interactive}
|
|
184
209
|
onToggle={() => toggleSelect(item.caseUniqueId)}
|
|
185
210
|
/>
|
|
186
211
|
))}
|
|
187
212
|
</div>
|
|
188
213
|
) : null}
|
|
189
|
-
{enableRefresh && caseSearch && caseFilter
|
|
214
|
+
{enableRefresh && caseSearch && isCaseFilterReady(caseFilter) ? (
|
|
190
215
|
<div className="skopon-resume-select-actions">
|
|
191
216
|
<Button
|
|
192
217
|
type="default"
|