@skopon-cool/form-sdk 0.1.6 → 0.1.8
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/components/AskUserFormCard.d.ts.map +1 -1
- package/dist/index.js +1733 -791
- package/dist/types/index.d.ts +8 -0
- package/package.json +1 -1
- package/src/adapter/formSchema.ts +26 -0
- package/src/blocks/case_multiselect/adapter.ts +13 -0
- package/src/blocks/resume_multiselect/adapter.ts +13 -0
- package/src/catalog/skoponCaseSelect.tsx +24 -5
- package/src/catalog/skoponResumeSelect.tsx +24 -5
- package/src/catalog/useSkoponBoundField.test.ts +26 -1
- package/src/catalog/useSkoponBoundField.ts +46 -0
- package/src/components/AskUserFormCard.tsx +1 -0
- package/src/types/index.ts +8 -0
package/dist/types/index.d.ts
CHANGED
|
@@ -72,10 +72,18 @@ export interface FormBlock {
|
|
|
72
72
|
defaultValue?: string | string[] | boolean;
|
|
73
73
|
/** 简历多选:是否显示「换一批」 */
|
|
74
74
|
resumeEnableRefresh?: boolean;
|
|
75
|
+
/** 简历多选:最少选中数量,配置值 ≥ 1 */
|
|
76
|
+
resumeMinCount?: number;
|
|
77
|
+
/** 简历多选:最多选中数量,配置值 ≥ 1 */
|
|
78
|
+
resumeMaxCount?: number;
|
|
75
79
|
/** 简历多选:列表筛选条件(持久化进 block json) */
|
|
76
80
|
resumeFilter?: FormResumeFilter;
|
|
77
81
|
/** 案例单选:是否显示「换一批」 */
|
|
78
82
|
caseEnableRefresh?: boolean;
|
|
83
|
+
/** 案例多选:最少选中数量,配置值 ≥ 1 */
|
|
84
|
+
caseMinCount?: number;
|
|
85
|
+
/** 案例多选:最多选中数量,配置值 ≥ 1 */
|
|
86
|
+
caseMaxCount?: number;
|
|
79
87
|
/** 案例单选:列表筛选条件(持久化进 block json) */
|
|
80
88
|
caseFilter?: FormCaseFilter;
|
|
81
89
|
}
|
package/package.json
CHANGED
|
@@ -23,6 +23,12 @@ function normalizeFileUploadCount(raw: unknown, fallback = 1): number {
|
|
|
23
23
|
return Math.max(0, Math.floor(num))
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function normalizeMultiselectCount(raw: unknown, fallback = 1): number {
|
|
27
|
+
const num = typeof raw === 'number' ? raw : Number(raw)
|
|
28
|
+
if (!Number.isFinite(num)) return fallback
|
|
29
|
+
return Math.max(1, Math.floor(num))
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
function normalizeDefaultValue(
|
|
27
33
|
type: FormBlockType,
|
|
28
34
|
raw: FormBlock['defaultValue'],
|
|
@@ -129,10 +135,26 @@ function normalizeBlock(raw: FormBlock): FormBlock {
|
|
|
129
135
|
: undefined,
|
|
130
136
|
resumeEnableRefresh:
|
|
131
137
|
type === 'resume_multiselect' ? migrated.resumeEnableRefresh !== false : undefined,
|
|
138
|
+
resumeMinCount:
|
|
139
|
+
type === 'resume_multiselect' && migrated.resumeMinCount != null
|
|
140
|
+
? normalizeMultiselectCount(migrated.resumeMinCount, 1)
|
|
141
|
+
: undefined,
|
|
142
|
+
resumeMaxCount:
|
|
143
|
+
type === 'resume_multiselect' && migrated.resumeMaxCount != null
|
|
144
|
+
? normalizeMultiselectCount(migrated.resumeMaxCount, 1)
|
|
145
|
+
: undefined,
|
|
132
146
|
resumeFilter:
|
|
133
147
|
type === 'resume_multiselect' ? normalizeResumeFilter(migrated.resumeFilter) : undefined,
|
|
134
148
|
caseEnableRefresh:
|
|
135
149
|
type === 'case_multiselect' ? migrated.caseEnableRefresh !== false : undefined,
|
|
150
|
+
caseMinCount:
|
|
151
|
+
type === 'case_multiselect' && migrated.caseMinCount != null
|
|
152
|
+
? normalizeMultiselectCount(migrated.caseMinCount, 1)
|
|
153
|
+
: undefined,
|
|
154
|
+
caseMaxCount:
|
|
155
|
+
type === 'case_multiselect' && migrated.caseMaxCount != null
|
|
156
|
+
? normalizeMultiselectCount(migrated.caseMaxCount, 1)
|
|
157
|
+
: undefined,
|
|
136
158
|
caseFilter:
|
|
137
159
|
type === 'case_multiselect' ? normalizeCaseFilter(migrated.caseFilter) : undefined,
|
|
138
160
|
}
|
|
@@ -203,6 +225,8 @@ export function createEmptyBlock(type: FormBlockType): FormBlock {
|
|
|
203
225
|
|
|
204
226
|
if (type === 'resume_multiselect') {
|
|
205
227
|
block.resumeEnableRefresh = true
|
|
228
|
+
block.resumeMinCount = 1
|
|
229
|
+
block.resumeMaxCount = 1
|
|
206
230
|
block.resumeFilter = {
|
|
207
231
|
names: [],
|
|
208
232
|
agentUniqueIds: [],
|
|
@@ -214,6 +238,8 @@ export function createEmptyBlock(type: FormBlockType): FormBlock {
|
|
|
214
238
|
|
|
215
239
|
if (type === 'case_multiselect') {
|
|
216
240
|
block.caseEnableRefresh = true
|
|
241
|
+
block.caseMinCount = 1
|
|
242
|
+
block.caseMaxCount = 1
|
|
217
243
|
block.caseFilter = { flowUniqueIds: [], pageSize: 20 }
|
|
218
244
|
block.defaultValue = []
|
|
219
245
|
}
|
|
@@ -39,6 +39,13 @@ function readCaseFilterFromNode(cf: Record<string, unknown>) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function readOptionalCount(raw: unknown): number | undefined {
|
|
43
|
+
if (raw === undefined || raw === null) return undefined
|
|
44
|
+
const num = typeof raw === 'number' ? raw : Number(raw)
|
|
45
|
+
if (!Number.isFinite(num) || num < 1) return undefined
|
|
46
|
+
return Math.floor(num)
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
export function caseMultiselectToComponent(
|
|
43
50
|
block: FormBlock,
|
|
44
51
|
ctx: BlockAdapterContext,
|
|
@@ -59,6 +66,8 @@ export function caseMultiselectToComponent(
|
|
|
59
66
|
flowUniqueIds: block.caseFilter?.flowUniqueIds ?? [],
|
|
60
67
|
pageSize: block.caseFilter?.pageSize ?? 20,
|
|
61
68
|
},
|
|
69
|
+
...(block.caseMinCount !== undefined ? { minCount: block.caseMinCount } : {}),
|
|
70
|
+
...(block.caseMaxCount !== undefined ? { maxCount: block.caseMaxCount } : {}),
|
|
62
71
|
value: { path },
|
|
63
72
|
})
|
|
64
73
|
}
|
|
@@ -84,6 +93,10 @@ export function caseMultiselectFromComponent(
|
|
|
84
93
|
if (node.caseFilter && typeof node.caseFilter === 'object') {
|
|
85
94
|
block.caseFilter = readCaseFilterFromNode(node.caseFilter as Record<string, unknown>)
|
|
86
95
|
}
|
|
96
|
+
const minCount = readOptionalCount(node.minCount)
|
|
97
|
+
if (minCount !== undefined) block.caseMinCount = minCount
|
|
98
|
+
const maxCount = readOptionalCount(node.maxCount)
|
|
99
|
+
if (maxCount !== undefined) block.caseMaxCount = maxCount
|
|
87
100
|
return block
|
|
88
101
|
}
|
|
89
102
|
|
|
@@ -5,6 +5,13 @@ function asLiteral(value: unknown): string | undefined {
|
|
|
5
5
|
return typeof value === 'string' ? value : undefined
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
function readOptionalCount(raw: unknown): number | undefined {
|
|
9
|
+
if (raw === undefined || raw === null) return undefined
|
|
10
|
+
const num = typeof raw === 'number' ? raw : Number(raw)
|
|
11
|
+
if (!Number.isFinite(num) || num < 1) return undefined
|
|
12
|
+
return Math.floor(num)
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
export function resumeMultiselectToComponent(
|
|
9
16
|
block: FormBlock,
|
|
10
17
|
ctx: BlockAdapterContext,
|
|
@@ -23,6 +30,8 @@ export function resumeMultiselectToComponent(
|
|
|
23
30
|
resumeUniqueIds: block.resumeFilter?.resumeUniqueIds ?? [],
|
|
24
31
|
pageSize: block.resumeFilter?.pageSize ?? 20,
|
|
25
32
|
},
|
|
33
|
+
...(block.resumeMinCount !== undefined ? { minCount: block.resumeMinCount } : {}),
|
|
34
|
+
...(block.resumeMaxCount !== undefined ? { maxCount: block.resumeMaxCount } : {}),
|
|
26
35
|
value: { path },
|
|
27
36
|
})
|
|
28
37
|
}
|
|
@@ -51,6 +60,10 @@ export function resumeMultiselectFromComponent(
|
|
|
51
60
|
pageSize: typeof rf.pageSize === 'number' ? rf.pageSize : 20,
|
|
52
61
|
}
|
|
53
62
|
}
|
|
63
|
+
const minCount = readOptionalCount(node.minCount)
|
|
64
|
+
if (minCount !== undefined) block.resumeMinCount = minCount
|
|
65
|
+
const maxCount = readOptionalCount(node.maxCount)
|
|
66
|
+
if (maxCount !== undefined) block.resumeMaxCount = maxCount
|
|
54
67
|
return block
|
|
55
68
|
}
|
|
56
69
|
|
|
@@ -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 { asStringArray, useSkoponBoundField } from './useSkoponBoundField'
|
|
9
|
+
import { asStringArray, clampStringArraySelection, isCardSelectionDisabled, readOptionalSelectCount, toggleStringArraySelection, useSkoponBoundField } from './useSkoponBoundField'
|
|
10
10
|
import { type CaseSearchItem, useCaseSearch } from './caseSearchContext'
|
|
11
11
|
|
|
12
12
|
function readString(value: unknown): string {
|
|
@@ -64,6 +64,8 @@ const SkoponCaseSelectApi = {
|
|
|
64
64
|
help: z.any().optional(),
|
|
65
65
|
enableRefresh: z.any().optional(),
|
|
66
66
|
caseFilter: z.any().optional(),
|
|
67
|
+
minCount: z.any().optional(),
|
|
68
|
+
maxCount: z.any().optional(),
|
|
67
69
|
value: z.any().optional(),
|
|
68
70
|
})
|
|
69
71
|
.passthrough(),
|
|
@@ -115,6 +117,8 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
115
117
|
const placeholder = readString(props.placeholder)
|
|
116
118
|
const help = readString(props.help)
|
|
117
119
|
const enableRefresh = props.enableRefresh !== false
|
|
120
|
+
const minCount = readOptionalSelectCount(props.minCount)
|
|
121
|
+
const maxCount = readOptionalSelectCount(props.maxCount)
|
|
118
122
|
const caseFilter = useMemo(() => readCaseFilter(props.caseFilter), [props.caseFilter])
|
|
119
123
|
const filterSig = filterKey(caseFilter)
|
|
120
124
|
|
|
@@ -128,6 +132,11 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
128
132
|
|
|
129
133
|
const selectedIds = asStringArray(value)
|
|
130
134
|
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const clamped = clampStringArraySelection(selectedIds, maxCount)
|
|
137
|
+
if (clamped !== null) setValue(clamped)
|
|
138
|
+
}, [maxCount, selectedIds, setValue])
|
|
139
|
+
|
|
131
140
|
const emptyHint = useMemo(() => {
|
|
132
141
|
if (!caseSearch) return '未配置案例搜索服务'
|
|
133
142
|
if (!isCaseFilterReady(caseFilter)) return '未配置案例列表筛选条件'
|
|
@@ -173,9 +182,13 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
173
182
|
|
|
174
183
|
const toggleSelect = (caseUniqueId: string) => {
|
|
175
184
|
if (!interactive) return
|
|
176
|
-
const next =
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
const next = toggleStringArraySelection(
|
|
186
|
+
selectedIds,
|
|
187
|
+
caseUniqueId,
|
|
188
|
+
minCount,
|
|
189
|
+
maxCount,
|
|
190
|
+
)
|
|
191
|
+
if (next === null) return
|
|
179
192
|
setValue(next)
|
|
180
193
|
}
|
|
181
194
|
|
|
@@ -205,7 +218,13 @@ function SkoponCaseSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
205
218
|
key={item.caseUniqueId}
|
|
206
219
|
item={item}
|
|
207
220
|
selected={selectedIds.includes(item.caseUniqueId)}
|
|
208
|
-
disabled={
|
|
221
|
+
disabled={isCardSelectionDisabled(
|
|
222
|
+
selectedIds,
|
|
223
|
+
item.caseUniqueId,
|
|
224
|
+
interactive,
|
|
225
|
+
minCount,
|
|
226
|
+
maxCount,
|
|
227
|
+
)}
|
|
209
228
|
onToggle={() => toggleSelect(item.caseUniqueId)}
|
|
210
229
|
/>
|
|
211
230
|
))}
|
|
@@ -6,7 +6,7 @@ import { createBinderlessComponentImplementation } from '@a2ui/react/v0_9'
|
|
|
6
6
|
import { z } from 'zod'
|
|
7
7
|
import type { FormResumeFilter } from '../types/index'
|
|
8
8
|
import { useA2uiPreviewMode } from './a2uiPreviewContext'
|
|
9
|
-
import { asStringArray, useSkoponBoundField } from './useSkoponBoundField'
|
|
9
|
+
import { asStringArray, clampStringArraySelection, isCardSelectionDisabled, readOptionalSelectCount, toggleStringArraySelection, useSkoponBoundField } from './useSkoponBoundField'
|
|
10
10
|
import {
|
|
11
11
|
type ResumeSearchItem,
|
|
12
12
|
type ResumeSearchWorkItem,
|
|
@@ -50,6 +50,8 @@ const SkoponResumeSelectApi = {
|
|
|
50
50
|
help: z.any().optional(),
|
|
51
51
|
enableRefresh: z.any().optional(),
|
|
52
52
|
resumeFilter: z.any().optional(),
|
|
53
|
+
minCount: z.any().optional(),
|
|
54
|
+
maxCount: z.any().optional(),
|
|
53
55
|
value: z.any().optional(),
|
|
54
56
|
})
|
|
55
57
|
.passthrough(),
|
|
@@ -168,6 +170,8 @@ function SkoponResumeSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
168
170
|
const placeholder = readString(props.placeholder)
|
|
169
171
|
const help = readString(props.help)
|
|
170
172
|
const enableRefresh = props.enableRefresh !== false
|
|
173
|
+
const minCount = readOptionalSelectCount(props.minCount)
|
|
174
|
+
const maxCount = readOptionalSelectCount(props.maxCount)
|
|
171
175
|
const resumeFilter = useMemo(() => readResumeFilter(props.resumeFilter), [props.resumeFilter])
|
|
172
176
|
const filterSig = filterKey(resumeFilter)
|
|
173
177
|
|
|
@@ -181,6 +185,11 @@ function SkoponResumeSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
181
185
|
|
|
182
186
|
const selectedIds = asStringArray(value)
|
|
183
187
|
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
const clamped = clampStringArraySelection(selectedIds, maxCount)
|
|
190
|
+
if (clamped !== null) setValue(clamped)
|
|
191
|
+
}, [maxCount, selectedIds, setValue])
|
|
192
|
+
|
|
184
193
|
const fetchPage = useCallback(
|
|
185
194
|
async (targetPage: number) => {
|
|
186
195
|
const filter = readResumeFilter(JSON.parse(filterSig) as FormResumeFilter)
|
|
@@ -219,9 +228,13 @@ function SkoponResumeSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
219
228
|
|
|
220
229
|
const toggleSelect = (resumeUniqueId: string) => {
|
|
221
230
|
if (!interactive) return
|
|
222
|
-
const next =
|
|
223
|
-
|
|
224
|
-
|
|
231
|
+
const next = toggleStringArraySelection(
|
|
232
|
+
selectedIds,
|
|
233
|
+
resumeUniqueId,
|
|
234
|
+
minCount,
|
|
235
|
+
maxCount,
|
|
236
|
+
)
|
|
237
|
+
if (next === null) return
|
|
225
238
|
setValue(next)
|
|
226
239
|
}
|
|
227
240
|
|
|
@@ -258,7 +271,13 @@ function SkoponResumeSelectPreview({ context }: { context: ComponentContext }) {
|
|
|
258
271
|
key={item.resumeUniqueId}
|
|
259
272
|
item={item}
|
|
260
273
|
selected={selectedIds.includes(item.resumeUniqueId)}
|
|
261
|
-
disabled={
|
|
274
|
+
disabled={isCardSelectionDisabled(
|
|
275
|
+
selectedIds,
|
|
276
|
+
item.resumeUniqueId,
|
|
277
|
+
interactive,
|
|
278
|
+
minCount,
|
|
279
|
+
maxCount,
|
|
280
|
+
)}
|
|
262
281
|
onToggle={() => toggleSelect(item.resumeUniqueId)}
|
|
263
282
|
/>
|
|
264
283
|
))}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { describe, it, expect } from 'vitest'
|
|
5
5
|
import type { ComponentContext } from '@a2ui/web_core/v0_9'
|
|
6
|
-
import { asStringArray, readBoundFieldValue } from './useSkoponBoundField'
|
|
6
|
+
import { asStringArray, clampStringArraySelection, readBoundFieldValue, toggleStringArraySelection } from './useSkoponBoundField'
|
|
7
7
|
|
|
8
8
|
function createMockContext(initial: unknown = []): {
|
|
9
9
|
context: ComponentContext
|
|
@@ -47,6 +47,31 @@ describe('readBoundFieldValue', () => {
|
|
|
47
47
|
})
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
+
describe('toggleStringArraySelection', () => {
|
|
51
|
+
it('blocks append when at maxCount', () => {
|
|
52
|
+
expect(toggleStringArraySelection(['a'], 'b', undefined, 1)).toBeNull()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('blocks deselect when at minCount', () => {
|
|
56
|
+
expect(toggleStringArraySelection(['a'], 'a', 1, undefined)).toBeNull()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('allows toggle within bounds', () => {
|
|
60
|
+
expect(toggleStringArraySelection([], 'a', 1, 2)).toEqual(['a'])
|
|
61
|
+
expect(toggleStringArraySelection(['a', 'b'], 'a', 1, 3)).toEqual(['b'])
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
describe('clampStringArraySelection', () => {
|
|
66
|
+
it('returns null when within maxCount', () => {
|
|
67
|
+
expect(clampStringArraySelection(['a'], 2)).toBeNull()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('trims to maxCount when over limit', () => {
|
|
71
|
+
expect(clampStringArraySelection(['a', 'b', 'c'], 2)).toEqual(['a', 'b'])
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
50
75
|
describe('file upload remove by uid index', () => {
|
|
51
76
|
it('removes only the file at the uid index when names duplicate', () => {
|
|
52
77
|
const currentNames = ['dup.txt', 'dup.txt', 'other.txt']
|
|
@@ -64,3 +64,49 @@ export function asStringArray(value: unknown): string[] {
|
|
|
64
64
|
if (typeof value === 'string' && value) return [value]
|
|
65
65
|
return []
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
export function readOptionalSelectCount(value: unknown): number | undefined {
|
|
69
|
+
if (value === undefined || value === null) return undefined
|
|
70
|
+
const num = typeof value === 'number' ? value : Number(value)
|
|
71
|
+
if (!Number.isFinite(num) || num < 1) return undefined
|
|
72
|
+
return Math.floor(num)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function toggleStringArraySelection(
|
|
76
|
+
selectedIds: string[],
|
|
77
|
+
itemId: string,
|
|
78
|
+
minCount: number | undefined,
|
|
79
|
+
maxCount: number | undefined,
|
|
80
|
+
): string[] | null {
|
|
81
|
+
const isSelected = selectedIds.includes(itemId)
|
|
82
|
+
if (isSelected) {
|
|
83
|
+
const next = selectedIds.filter((id) => id !== itemId)
|
|
84
|
+
if (minCount !== undefined && next.length < minCount) return null
|
|
85
|
+
return next
|
|
86
|
+
}
|
|
87
|
+
if (maxCount !== undefined && selectedIds.length >= maxCount) return null
|
|
88
|
+
return [...selectedIds, itemId]
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function isCardSelectionDisabled(
|
|
92
|
+
selectedIds: string[],
|
|
93
|
+
itemId: string,
|
|
94
|
+
interactive: boolean,
|
|
95
|
+
minCount: number | undefined,
|
|
96
|
+
maxCount: number | undefined,
|
|
97
|
+
): boolean {
|
|
98
|
+
if (!interactive) return true
|
|
99
|
+
const isSelected = selectedIds.includes(itemId)
|
|
100
|
+
if (!isSelected && maxCount !== undefined && selectedIds.length >= maxCount) return true
|
|
101
|
+
if (isSelected && minCount !== undefined && selectedIds.length <= minCount) return true
|
|
102
|
+
return false
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** 超出 maxCount 时返回裁剪后的数组,否则返回 null(无需变更)。 */
|
|
106
|
+
export function clampStringArraySelection(
|
|
107
|
+
selectedIds: string[],
|
|
108
|
+
maxCount: number | undefined,
|
|
109
|
+
): string[] | null {
|
|
110
|
+
if (maxCount === undefined || selectedIds.length <= maxCount) return null
|
|
111
|
+
return selectedIds.slice(0, maxCount)
|
|
112
|
+
}
|
|
@@ -165,6 +165,7 @@ export default function AskUserFormCard({
|
|
|
165
165
|
<CurlSubmitBlock
|
|
166
166
|
payload={payload}
|
|
167
167
|
callbackUrl={callbackUrl}
|
|
168
|
+
copyMode="submitFields"
|
|
168
169
|
unpublishedFormId={formDisabled && resolvedFormUniqueId ? resolvedFormUniqueId : undefined}
|
|
169
170
|
onNotify={onNotify}
|
|
170
171
|
/>
|
package/src/types/index.ts
CHANGED
|
@@ -129,10 +129,18 @@ export interface FormBlock {
|
|
|
129
129
|
defaultValue?: string | string[] | boolean
|
|
130
130
|
/** 简历多选:是否显示「换一批」 */
|
|
131
131
|
resumeEnableRefresh?: boolean
|
|
132
|
+
/** 简历多选:最少选中数量,配置值 ≥ 1 */
|
|
133
|
+
resumeMinCount?: number
|
|
134
|
+
/** 简历多选:最多选中数量,配置值 ≥ 1 */
|
|
135
|
+
resumeMaxCount?: number
|
|
132
136
|
/** 简历多选:列表筛选条件(持久化进 block json) */
|
|
133
137
|
resumeFilter?: FormResumeFilter
|
|
134
138
|
/** 案例单选:是否显示「换一批」 */
|
|
135
139
|
caseEnableRefresh?: boolean
|
|
140
|
+
/** 案例多选:最少选中数量,配置值 ≥ 1 */
|
|
141
|
+
caseMinCount?: number
|
|
142
|
+
/** 案例多选:最多选中数量,配置值 ≥ 1 */
|
|
143
|
+
caseMaxCount?: number
|
|
136
144
|
/** 案例单选:列表筛选条件(持久化进 block json) */
|
|
137
145
|
caseFilter?: FormCaseFilter
|
|
138
146
|
}
|