@skopon-cool/form-sdk 0.6.1 → 0.6.2

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.
Files changed (48) hide show
  1. package/README.md +16 -0
  2. package/dist/adapter/formSchema.d.ts +3 -0
  3. package/dist/adapter/formSchema.d.ts.map +1 -1
  4. package/dist/blocks/resume_multiselect/adapter.d.ts.map +1 -1
  5. package/dist/catalog/contentSearchContext.d.ts +35 -0
  6. package/dist/catalog/contentSearchContext.d.ts.map +1 -0
  7. package/dist/catalog/pairResumeContent.d.ts +20 -0
  8. package/dist/catalog/pairResumeContent.d.ts.map +1 -0
  9. package/dist/catalog/skoponResumeSelect.d.ts.map +1 -1
  10. package/dist/client/contentSearchClient.d.ts +36 -0
  11. package/dist/client/contentSearchClient.d.ts.map +1 -0
  12. package/dist/client/resumeSearchClient.d.ts.map +1 -1
  13. package/dist/client/skoponSdkClients.d.ts +4 -0
  14. package/dist/client/skoponSdkClients.d.ts.map +1 -1
  15. package/dist/components/AskUserFormCard.d.ts +3 -0
  16. package/dist/components/AskUserFormCard.d.ts.map +1 -1
  17. package/dist/components/SkoponA2uiStreamRenderer.d.ts +4 -1
  18. package/dist/components/SkoponA2uiStreamRenderer.d.ts.map +1 -1
  19. package/dist/components/SkoponFormRenderer.d.ts +3 -0
  20. package/dist/components/SkoponFormRenderer.d.ts.map +1 -1
  21. package/dist/form-sdk.css +1 -1
  22. package/dist/index.d.ts +4 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1858 -1557
  25. package/dist/types/index.d.ts +25 -1
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/package.json +1 -1
  28. package/src/adapter/formSchema.test.ts +8 -0
  29. package/src/adapter/formSchema.ts +49 -0
  30. package/src/blocks/resume_multiselect/adapter.ts +31 -0
  31. package/src/catalog/contentSearchContext.tsx +53 -0
  32. package/src/catalog/pairResumeContent.test.ts +34 -0
  33. package/src/catalog/pairResumeContent.ts +55 -0
  34. package/src/catalog/skoponResumeSelect.tsx +348 -153
  35. package/src/catalog/skoponSelectLoading.test.tsx +84 -5
  36. package/src/client/contentSearchClient.test.ts +123 -0
  37. package/src/client/contentSearchClient.ts +156 -0
  38. package/src/client/resumeSearchClient.test.ts +5 -0
  39. package/src/client/resumeSearchClient.ts +5 -0
  40. package/src/client/skoponSdkClients.ts +9 -0
  41. package/src/components/AskUserFormCard.tsx +5 -0
  42. package/src/components/SkoponA2uiStreamRenderer.tsx +15 -9
  43. package/src/components/SkoponFormRenderer.tsx +20 -12
  44. package/src/index.ts +16 -0
  45. package/src/styles/a2ui-preview.css +4 -4
  46. package/src/styles/index.css +158 -13
  47. package/src/submit/submit.test.ts +1 -0
  48. package/src/types/index.ts +26 -1
@@ -40,12 +40,30 @@ export interface FormBlockCondition {
40
40
  /** 简历多选组件:渲染时用于 /univ/resume/search 的筛选条件 */
41
41
  export interface FormResumeFilter {
42
42
  names?: string[];
43
- /** Agent 类型(编辑器辅助,运行时不用) */
43
+ /**
44
+ * 智能体类型 unique_id。
45
+ * 运行时作为 agent_type:先找出该类型的智能体,再查他们的简历。
46
+ */
44
47
  agentKind?: string;
45
48
  agentUniqueIds?: string[];
49
+ /** 智能体标签 unique_id,多值 AND;与 agentKind 一起定位智能体后再查简历 */
50
+ tagUniqueIds?: string[];
46
51
  resumeUniqueIds?: string[];
47
52
  pageSize?: number;
48
53
  }
54
+ /** 内容制作搜索:渲染时用于 /univ/flow/list?owner_scope=content */
55
+ export interface FormContentFilter {
56
+ /** 流程类型 unique_id,默认 content-production */
57
+ flowType?: string;
58
+ /** 流程类别 unique_id */
59
+ category?: string;
60
+ /** 内容标签 unique_id */
61
+ tagUniqueIds?: string[];
62
+ /** 多标签匹配方式;all=全部命中,any=命中任一 */
63
+ tagMatch?: 'all' | 'any';
64
+ /** 每次向内容接口请求的条数,不是一屏展示张数 */
65
+ pageSize?: number;
66
+ }
49
67
  /** 案例多选组件:渲染时用于 /univ/case/list 的筛选条件 */
50
68
  export interface FormCaseFilter {
51
69
  /** Agent 类型(编辑器辅助,运行时不用) */
@@ -94,8 +112,14 @@ export interface FormBlock {
94
112
  resumeMinCount?: number;
95
113
  /** 简历多选:最多选中数量,配置值 ≥ 1 */
96
114
  resumeMaxCount?: number;
115
+ /** 简历多选:一轮展示几张,默认 5。不是最多可选数,也不是接口 page_size */
116
+ /** content-only 仅选内容,提交 flow_unique_id;默认仍为简历与内容组合。 */
117
+ resumeDisplayMode?: 'profile-content' | 'content-only';
118
+ resumeDisplayCount?: number;
97
119
  /** 简历多选:列表筛选条件(持久化进 block json) */
98
120
  resumeFilter?: FormResumeFilter;
121
+ /** 简历多选:内容制作筛选(持久化进 block json) */
122
+ contentFilter?: FormContentFilter;
99
123
  /** 案例单选:是否显示「换一批」 */
100
124
  caseEnableRefresh?: boolean;
101
125
  /** 案例多选:最少选中数量,配置值 ≥ 1 */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
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;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,kBAAkB;AACpB,4CAA4C;GAC1C,mBAAmB,GACnB,OAAO,GACP,OAAO,GACP,OAAO,GACP,KAAK,CAAA;AAET,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,MAAM,MAAM,qBAAqB,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,UAAU,CAAA;AAEtE,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;IACxB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,yCAAyC;AACzC,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,aAAa,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC/B,mBAAmB,CAAC,EAAE,uBAAuB,CAAA;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAA;IAC1C,2CAA2C;IAC3C,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qBAAqB;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,0BAA0B;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0BAA0B;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,+CAA+C;IAC/C,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,cAAc,CAAA;IACtD,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,mCAAmC;IACnC,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,mCAAmC;IACnC,aAAa,CAAC,EAAE,iBAAiB,CAAA;IACjC,qBAAqB;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,mCAAmC;IACnC,UAAU,CAAC,EAAE,cAAc,CAAA;IAC3B,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,UAAU,EAAE,cAAc,CAAA;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE7D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE3D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE9D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE/D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAOjE;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B,UAAU,CAAC,EAAE,cAAc,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,CAAC,EAAE,UAAU,CAAA;IAC3B,IAAI,CAAC,EAAE,cAAc,CAAA;CACtB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.6.1",
6
+ "version": "0.6.2",
7
7
  "description": "Skopon form rendering SDK (A2UI + form_definition) with submit helpers",
8
8
  "type": "module",
9
9
  "sideEffects": [
@@ -188,6 +188,7 @@ describe('normalizeFormDefinition preserves needLLM and editor fields', () => {
188
188
  agentKind: 'management',
189
189
  names: [],
190
190
  agentUniqueIds: [],
191
+ tagUniqueIds: ['tag-hot'],
191
192
  resumeUniqueIds: [],
192
193
  pageSize: 20,
193
194
  },
@@ -196,6 +197,13 @@ describe('normalizeFormDefinition preserves needLLM and editor fields', () => {
196
197
  jsonSchema: {},
197
198
  })
198
199
  expect(def.blocks[0]?.resumeFilter?.agentKind).toBe('management')
200
+ expect(def.blocks[0]?.resumeFilter?.tagUniqueIds).toEqual(['tag-hot'])
201
+ expect(def.blocks[0]?.resumeDisplayCount).toBe(5)
202
+ expect(def.blocks[0]?.contentFilter).toMatchObject({
203
+ flowType: 'content-production',
204
+ tagUniqueIds: [],
205
+ pageSize: 20,
206
+ })
199
207
  })
200
208
  })
201
209
 
@@ -2,6 +2,7 @@ import type {
2
2
  FormBlock,
3
3
  FormBlockType,
4
4
  FormCaseFilter,
5
+ FormContentFilter,
5
6
  FormResumeFilter,
6
7
  FormJsonSchema,
7
8
  FormSchema,
@@ -136,6 +137,9 @@ function normalizeResumeFilter(raw: FormResumeFilter | undefined): FormResumeFil
136
137
  agentUniqueIds: Array.isArray(raw?.agentUniqueIds)
137
138
  ? raw!.agentUniqueIds.map(String).filter(Boolean)
138
139
  : [],
140
+ tagUniqueIds: Array.isArray(raw?.tagUniqueIds)
141
+ ? raw!.tagUniqueIds.map(String).filter(Boolean)
142
+ : [],
139
143
  resumeUniqueIds: Array.isArray(raw?.resumeUniqueIds)
140
144
  ? raw!.resumeUniqueIds.map(String).filter(Boolean)
141
145
  : [],
@@ -143,6 +147,35 @@ function normalizeResumeFilter(raw: FormResumeFilter | undefined): FormResumeFil
143
147
  }
144
148
  }
145
149
 
150
+ export const DEFAULT_CONTENT_FLOW_TYPE = 'content-production'
151
+ export const DEFAULT_RESUME_DISPLAY_COUNT = 5
152
+
153
+ export function normalizeResumeDisplayCount(raw: unknown): number {
154
+ const num = typeof raw === 'number' ? raw : Number(raw)
155
+ if (!Number.isFinite(num) || num < 1) return DEFAULT_RESUME_DISPLAY_COUNT
156
+ return Math.min(100, Math.floor(num))
157
+ }
158
+
159
+ function normalizeContentFilter(raw: FormContentFilter | undefined): FormContentFilter {
160
+ const pageSizeRaw = typeof raw?.pageSize === 'number' ? raw.pageSize : Number(raw?.pageSize)
161
+ const pageSize =
162
+ Number.isFinite(pageSizeRaw) && pageSizeRaw >= 1 && pageSizeRaw <= 100
163
+ ? Math.floor(pageSizeRaw)
164
+ : 20
165
+ const flowType = raw?.flowType?.trim() || DEFAULT_CONTENT_FLOW_TYPE
166
+ const category = raw?.category?.trim() || undefined
167
+ const tagMatch = raw?.tagMatch === 'any' ? 'any' : 'all'
168
+ return {
169
+ flowType,
170
+ ...(category ? { category } : {}),
171
+ tagUniqueIds: Array.isArray(raw?.tagUniqueIds)
172
+ ? raw.tagUniqueIds.map(String).filter(Boolean)
173
+ : [],
174
+ tagMatch,
175
+ pageSize,
176
+ }
177
+ }
178
+
146
179
  function migrateLegacyBlock(raw: FormBlock): FormBlock {
147
180
  if (raw.type !== 'case_singleselect') return raw
148
181
  const defaultValue =
@@ -204,8 +237,17 @@ function normalizeBlock(raw: FormBlock): FormBlock {
204
237
  type === 'resume_multiselect' && migrated.resumeMaxCount != null
205
238
  ? normalizeMultiselectCount(migrated.resumeMaxCount, 1)
206
239
  : undefined,
240
+ resumeDisplayMode: type === 'resume_multiselect'
241
+ ? (migrated.resumeDisplayMode === 'content-only' ? 'content-only' : 'profile-content')
242
+ : undefined,
243
+ resumeDisplayCount:
244
+ type === 'resume_multiselect'
245
+ ? normalizeResumeDisplayCount(migrated.resumeDisplayCount)
246
+ : undefined,
207
247
  resumeFilter:
208
248
  type === 'resume_multiselect' ? normalizeResumeFilter(migrated.resumeFilter) : undefined,
249
+ contentFilter:
250
+ type === 'resume_multiselect' ? normalizeContentFilter(migrated.contentFilter) : undefined,
209
251
  caseEnableRefresh:
210
252
  type === 'case_multiselect' ? migrated.caseEnableRefresh !== false : undefined,
211
253
  caseMinCount:
@@ -460,9 +502,16 @@ export function createEmptyBlock(type: FormBlockType): FormBlock {
460
502
  block.resumeEnableRefresh = true
461
503
  block.resumeMinCount = 1
462
504
  block.resumeMaxCount = 1
505
+ block.resumeDisplayCount = DEFAULT_RESUME_DISPLAY_COUNT
506
+ block.contentFilter = {
507
+ flowType: DEFAULT_CONTENT_FLOW_TYPE,
508
+ tagUniqueIds: [],
509
+ pageSize: 20,
510
+ }
463
511
  block.resumeFilter = {
464
512
  names: [],
465
513
  agentUniqueIds: [],
514
+ tagUniqueIds: [],
466
515
  resumeUniqueIds: [],
467
516
  pageSize: 20,
468
517
  }
@@ -24,9 +24,22 @@ export function resumeMultiselectToComponent(
24
24
  placeholder: block.placeholder ?? '',
25
25
  help: block.help ?? '',
26
26
  enableRefresh: block.resumeEnableRefresh !== false,
27
+ resumeDisplayMode: block.resumeDisplayMode ?? 'profile-content',
28
+ resumeDisplayCount: block.resumeDisplayCount ?? 5,
29
+ contentFilter: {
30
+ flowType: block.contentFilter?.flowType?.trim() || 'content-production',
31
+ ...(block.contentFilter?.category?.trim()
32
+ ? { category: block.contentFilter.category.trim() }
33
+ : {}),
34
+ tagUniqueIds: block.contentFilter?.tagUniqueIds ?? [],
35
+ tagMatch: block.contentFilter?.tagMatch === 'any' ? 'any' : 'all',
36
+ pageSize: block.contentFilter?.pageSize ?? 20,
37
+ },
27
38
  resumeFilter: {
28
39
  names: block.resumeFilter?.names ?? [],
40
+ ...(block.resumeFilter?.agentKind ? { agentKind: block.resumeFilter.agentKind } : {}),
29
41
  agentUniqueIds: block.resumeFilter?.agentUniqueIds ?? [],
42
+ tagUniqueIds: block.resumeFilter?.tagUniqueIds ?? [],
30
43
  resumeUniqueIds: block.resumeFilter?.resumeUniqueIds ?? [],
31
44
  pageSize: block.resumeFilter?.pageSize ?? 20,
32
45
  },
@@ -46,6 +59,7 @@ export function resumeMultiselectFromComponent(
46
59
  ...base('resume_multiselect'),
47
60
  name,
48
61
  resumeEnableRefresh: node.enableRefresh !== false,
62
+ resumeDisplayMode: node.resumeDisplayMode === 'content-only' ? 'content-only' : 'profile-content',
49
63
  }
50
64
  const placeholder = helpers.asLiteral(node.placeholder)
51
65
  if (placeholder) block.placeholder = placeholder
@@ -53,13 +67,30 @@ export function resumeMultiselectFromComponent(
53
67
  if (help) block.help = help
54
68
  if (node.resumeFilter && typeof node.resumeFilter === 'object') {
55
69
  const rf = node.resumeFilter as Record<string, unknown>
70
+ const agentKind = helpers.asLiteral(rf.agentKind)?.trim()
56
71
  block.resumeFilter = {
57
72
  names: Array.isArray(rf.names) ? rf.names.map(String) : [],
73
+ ...(agentKind ? { agentKind } : {}),
58
74
  agentUniqueIds: Array.isArray(rf.agentUniqueIds) ? rf.agentUniqueIds.map(String) : [],
75
+ tagUniqueIds: Array.isArray(rf.tagUniqueIds) ? rf.tagUniqueIds.map(String).filter(Boolean) : [],
59
76
  resumeUniqueIds: Array.isArray(rf.resumeUniqueIds) ? rf.resumeUniqueIds.map(String) : [],
60
77
  pageSize: typeof rf.pageSize === 'number' ? rf.pageSize : 20,
61
78
  }
62
79
  }
80
+ const displayCount = readOptionalCount(node.resumeDisplayCount)
81
+ if (displayCount !== undefined) block.resumeDisplayCount = displayCount
82
+ if (node.contentFilter && typeof node.contentFilter === 'object') {
83
+ const cf = node.contentFilter as Record<string, unknown>
84
+ const flowType = helpers.asLiteral(cf.flowType)?.trim()
85
+ const category = helpers.asLiteral(cf.category)?.trim()
86
+ block.contentFilter = {
87
+ flowType: flowType || 'content-production',
88
+ ...(category ? { category } : {}),
89
+ tagUniqueIds: Array.isArray(cf.tagUniqueIds) ? cf.tagUniqueIds.map(String).filter(Boolean) : [],
90
+ tagMatch: cf.tagMatch === 'any' ? 'any' : 'all',
91
+ pageSize: typeof cf.pageSize === 'number' ? cf.pageSize : 20,
92
+ }
93
+ }
63
94
  const minCount = readOptionalCount(node.minCount)
64
95
  if (minCount !== undefined) block.resumeMinCount = minCount
65
96
  const maxCount = readOptionalCount(node.maxCount)
@@ -0,0 +1,53 @@
1
+ import { createContext, useContext, type ReactNode } from 'react'
2
+ import type { FormContentFilter } from '../types/index'
3
+
4
+ export interface ContentSearchItem {
5
+ flowUniqueId: string
6
+ flowId?: number
7
+ name: string
8
+ description?: string
9
+ /** 内容方案标签的展示文案 */
10
+ tagLabels?: string[]
11
+ /** 最新案例名;没有案例时用流程名 */
12
+ title: string
13
+ platform?: string | null
14
+ coverUrl?: string | null
15
+ /** 可播放的视频地址;没有视频时为空 */
16
+ mediaUrl?: string | null
17
+ mediaKind?: 'video' | 'image' | null
18
+ link?: string
19
+ }
20
+
21
+ export interface ContentSearchParams {
22
+ filter: FormContentFilter
23
+ page: number
24
+ }
25
+
26
+ export interface ContentSearchResult {
27
+ list: ContentSearchItem[]
28
+ total: number
29
+ page: number
30
+ pageSize: number
31
+ }
32
+
33
+ export type ContentSearchFn = (params: ContentSearchParams) => Promise<ContentSearchResult>
34
+
35
+ const ContentSearchContext = createContext<ContentSearchFn | null>(null)
36
+
37
+ export function ContentSearchProvider({
38
+ contentSearch,
39
+ children,
40
+ }: {
41
+ contentSearch: ContentSearchFn | null | undefined
42
+ children: ReactNode
43
+ }) {
44
+ return (
45
+ <ContentSearchContext.Provider value={contentSearch ?? null}>
46
+ {children}
47
+ </ContentSearchContext.Provider>
48
+ )
49
+ }
50
+
51
+ export function useContentSearch(): ContentSearchFn | null {
52
+ return useContext(ContentSearchContext)
53
+ }
@@ -0,0 +1,34 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { advanceCursor, nextPageForWindow, windowIndexes } from './pairResumeContent'
3
+
4
+ describe('resume and content windows', () => {
5
+ it('pairs independent cursors and wraps only the side that is used up', () => {
6
+ let resumeCursor = 0
7
+ let contentCursor = 0
8
+ const displayCount = 3
9
+ const rounds = [
10
+ [[1, 2, 3], [1, 2, 3]],
11
+ [[4, 5, 6], [4, 5, 6]],
12
+ [[7, 8, 9], [7, 8, 9]],
13
+ [[10, 1, 2], [10, 11, 12]],
14
+ ]
15
+ for (const [resumes, contents] of rounds) {
16
+ expect(windowIndexes(resumeCursor, displayCount, 10).map((index) => index + 1)).toEqual(resumes)
17
+ expect(windowIndexes(contentCursor, displayCount, 100).map((index) => index + 1)).toEqual(contents)
18
+ resumeCursor = advanceCursor(resumeCursor, displayCount, 10)
19
+ contentCursor = advanceCursor(contentCursor, displayCount, 100)
20
+ }
21
+ })
22
+
23
+ it('fetches the next page only when a window index is past the cache and more pages exist', () => {
24
+ const cached = { itemCount: 20, total: 100, fetchedPage: 1, pageSize: 20 }
25
+ expect(nextPageForWindow(cached, windowIndexes(0, 3, 100))).toBeNull()
26
+ expect(nextPageForWindow(cached, windowIndexes(18, 3, 100))).toBe(2)
27
+ expect(
28
+ nextPageForWindow(
29
+ { itemCount: 10, total: 10, fetchedPage: 1, pageSize: 20 },
30
+ windowIndexes(9, 3, 10),
31
+ ),
32
+ ).toBeNull()
33
+ })
34
+ })
@@ -0,0 +1,55 @@
1
+ export const DEFAULT_RESUME_DISPLAY_COUNT = 5
2
+
3
+ export interface PageCacheSnapshot {
4
+ itemCount: number
5
+ total: number
6
+ fetchedPage: number
7
+ pageSize: number
8
+ }
9
+
10
+ export function normalizeDisplayCount(raw: unknown, fallback = DEFAULT_RESUME_DISPLAY_COUNT): number {
11
+ const num = typeof raw === 'number' ? raw : Number(raw)
12
+ if (!Number.isFinite(num) || num < 1) return fallback
13
+ return Math.min(100, Math.floor(num))
14
+ }
15
+
16
+ export function pairKey(resumeUniqueId: string, flowUniqueId: string): string {
17
+ return `${resumeUniqueId}|${flowUniqueId}`
18
+ }
19
+
20
+ export function hasMorePages(cache: PageCacheSnapshot): boolean {
21
+ if (cache.total <= 0 || cache.pageSize <= 0) return false
22
+ return cache.fetchedPage * cache.pageSize < cache.total
23
+ }
24
+
25
+ export function advanceCursor(cursor: number, displayCount: number, total: number): number {
26
+ if (total <= 0) return 0
27
+ const step = Math.max(1, displayCount)
28
+ return (((cursor % total) + total) % total + step) % total
29
+ }
30
+
31
+ /** 一轮要展示的下标。总数不够展示条数时只取总数那么多。 */
32
+ export function windowIndexes(cursor: number, displayCount: number, total: number): number[] {
33
+ if (total <= 0 || displayCount <= 0) return []
34
+ const count = Math.min(displayCount, total)
35
+ const start = ((cursor % total) + total) % total
36
+ return Array.from({ length: count }, (_, index) => (start + index) % total)
37
+ }
38
+
39
+ /**
40
+ * 窗口里有下标还没进缓存,并且接口还有下一页时,返回要请求的页码。
41
+ * 已经拿完则返回 null,调用方用缓存开头接上。
42
+ */
43
+ export function nextPageForWindow(cache: PageCacheSnapshot, indexes: number[]): number | null {
44
+ if (indexes.length === 0) return null
45
+ if (!indexes.some((index) => index >= cache.itemCount)) return null
46
+ if (!hasMorePages(cache)) return null
47
+ return cache.fetchedPage + 1
48
+ }
49
+
50
+ export function takeWindow<T>(items: T[], cursor: number, displayCount: number, total: number): T[] {
51
+ const indexes = windowIndexes(cursor, displayCount, total)
52
+ if (indexes.length === 0) return []
53
+ if (indexes.some((index) => index >= items.length)) return []
54
+ return indexes.map((index) => items[index])
55
+ }