@alicloud/appflow-chat 0.0.1-beta.2 → 0.0.1-beta.4
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/appflow-chat.cjs.js +252 -133
- package/dist/appflow-chat.esm.js +11261 -10184
- package/dist/types/index.d.ts +86 -51
- package/package.json +1 -1
- package/src/components/HumanVerify/CustomParamsRenderer/ArrayField.tsx +162 -7
- package/src/components/HumanVerify/CustomParamsRenderer/EnumField.tsx +199 -0
- package/src/components/HumanVerify/CustomParamsRenderer/FieldRenderer.tsx +152 -8
- package/src/components/HumanVerify/CustomParamsRenderer/FileField.tsx +509 -0
- package/src/components/HumanVerify/CustomParamsRenderer/ObjectField.tsx +10 -3
- package/src/components/HumanVerify/CustomParamsRenderer/TimeField.tsx +104 -0
- package/src/components/HumanVerify/CustomParamsRenderer/index.tsx +16 -2
- package/src/components/HumanVerify/CustomParamsRenderer/types.ts +231 -5
- package/src/components/HumanVerify/HistoryCard.tsx +39 -21
- package/src/components/HumanVerify/HumanVerify.tsx +23 -45
- package/src/components/MessageBubble.tsx +4 -10
- package/src/components/RichMessageBubble.tsx +2 -2
- package/src/index.ts +1 -0
- package/src/markdown/components/Mermaid.tsx +265 -0
- package/src/markdown/index.tsx +7 -0
- package/src/utils/loadMermaid.ts +40 -0
|
@@ -6,12 +6,16 @@ import {
|
|
|
6
6
|
CustomParamSchema,
|
|
7
7
|
ValidationResult,
|
|
8
8
|
validateCustomParams,
|
|
9
|
+
sortPropertiesByOrder,
|
|
9
10
|
} from './types';
|
|
10
11
|
|
|
11
12
|
export * from './types';
|
|
12
13
|
export { FieldRenderer } from './FieldRenderer';
|
|
13
14
|
export { ArrayField } from './ArrayField';
|
|
14
15
|
export { ObjectField } from './ObjectField';
|
|
16
|
+
export { TimeField } from './TimeField';
|
|
17
|
+
export { FileField } from './FileField';
|
|
18
|
+
export { EnumField } from './EnumField';
|
|
15
19
|
|
|
16
20
|
// ==================== Styled Components ====================
|
|
17
21
|
|
|
@@ -42,6 +46,9 @@ const EmptyState = styled.div`
|
|
|
42
46
|
* name: { Type: 'string', Title: '名称', Description: '请输入名称' },
|
|
43
47
|
* age: { Type: 'number', Title: '年龄' },
|
|
44
48
|
* enabled: { Type: 'boolean', Title: '是否启用' },
|
|
49
|
+
* date: { Type: 'time', Title: '日期', TimeSubType: 'year-month-day' },
|
|
50
|
+
* file: { Type: 'file', Title: '文件', FileSubType: 'image' },
|
|
51
|
+
* status: { Type: 'string', Title: '状态', EnumValues: ['active', 'inactive'], EnumDisplayStyle: 'radio' },
|
|
45
52
|
* tags: {
|
|
46
53
|
* Type: 'array',
|
|
47
54
|
* Title: '标签',
|
|
@@ -72,6 +79,8 @@ export const CustomParamsRenderer: React.FC<CustomParamsRendererProps> = ({
|
|
|
72
79
|
onChange,
|
|
73
80
|
disabled = false,
|
|
74
81
|
errors = {},
|
|
82
|
+
uploadSender,
|
|
83
|
+
fileUploader,
|
|
75
84
|
}) => {
|
|
76
85
|
const Properties = schema?.Properties;
|
|
77
86
|
const Required = schema?.Required || [];
|
|
@@ -96,9 +105,12 @@ export const CustomParamsRenderer: React.FC<CustomParamsRendererProps> = ({
|
|
|
96
105
|
);
|
|
97
106
|
}
|
|
98
107
|
|
|
108
|
+
// 使用排序后的属性列表进行渲染
|
|
109
|
+
const sortedProperties = sortPropertiesByOrder(Properties);
|
|
110
|
+
|
|
99
111
|
return (
|
|
100
112
|
<CustomParamsRendererContainer>
|
|
101
|
-
{
|
|
113
|
+
{sortedProperties?.map(([propertyName, propertySchema]) => {
|
|
102
114
|
const isRequired = Required.includes(propertyName);
|
|
103
115
|
|
|
104
116
|
return (
|
|
@@ -113,6 +125,8 @@ export const CustomParamsRenderer: React.FC<CustomParamsRendererProps> = ({
|
|
|
113
125
|
level={0}
|
|
114
126
|
errors={errors}
|
|
115
127
|
fieldPath=""
|
|
128
|
+
uploadSender={uploadSender}
|
|
129
|
+
fileUploader={fileUploader}
|
|
116
130
|
/>
|
|
117
131
|
);
|
|
118
132
|
})}
|
|
@@ -163,4 +177,4 @@ export const useCustomParamsRenderer = (schema: CustomParamSchema) => {
|
|
|
163
177
|
};
|
|
164
178
|
};
|
|
165
179
|
|
|
166
|
-
export default CustomParamsRenderer;
|
|
180
|
+
export default CustomParamsRenderer;
|
|
@@ -1,4 +1,102 @@
|
|
|
1
|
-
|
|
1
|
+
// ============ 上传相关类型定义 ============
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 上传请求参数
|
|
5
|
+
*/
|
|
6
|
+
export interface UploadRequestParams {
|
|
7
|
+
/** 事件类型:uploadToken-获取上传凭证,uploadFile-获取文件ID */
|
|
8
|
+
eventType: 'uploadToken' | 'uploadFile';
|
|
9
|
+
/** 文件名 */
|
|
10
|
+
fileName: string;
|
|
11
|
+
/** 文件下载 URL(uploadFile 时需要) */
|
|
12
|
+
content?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 上传 Token 响应
|
|
17
|
+
*/
|
|
18
|
+
export interface UploadTokenResponse {
|
|
19
|
+
/** 预签名上传 URL */
|
|
20
|
+
uploadUrl: string;
|
|
21
|
+
/** 文件下载 URL */
|
|
22
|
+
downloadUrl: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 上传文件响应
|
|
27
|
+
*/
|
|
28
|
+
export interface UploadFileResponse {
|
|
29
|
+
/** 文件 ID */
|
|
30
|
+
fileId: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 上传发送方法类型
|
|
35
|
+
* 用于发送上传相关的事件请求
|
|
36
|
+
*/
|
|
37
|
+
export type UploadSender = (params: UploadRequestParams) => Promise<string | null>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 文件上传方法类型
|
|
41
|
+
* 用于实际执行文件上传到 OSS
|
|
42
|
+
*/
|
|
43
|
+
export type FileUploader = (file: Blob, uploadUrl: string) => Promise<void>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 上传配置
|
|
47
|
+
*/
|
|
48
|
+
export interface UploadConfig {
|
|
49
|
+
/** 上传发送方法 */
|
|
50
|
+
uploadSender?: UploadSender;
|
|
51
|
+
/** 文件上传方法 */
|
|
52
|
+
fileUploader?: FileUploader;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ============ 基础类型定义 ============
|
|
56
|
+
|
|
57
|
+
// 基础类型
|
|
58
|
+
export type BasicParamType = 'string' | 'number' | 'boolean';
|
|
59
|
+
|
|
60
|
+
// 复合类型
|
|
61
|
+
export type ComplexParamType = 'array' | 'object';
|
|
62
|
+
|
|
63
|
+
// 扩展类型
|
|
64
|
+
export type ExtendedParamType = 'time' | 'file';
|
|
65
|
+
|
|
66
|
+
// 所有参数类型
|
|
67
|
+
export type ParamType = BasicParamType | ComplexParamType | ExtendedParamType;
|
|
68
|
+
|
|
69
|
+
// 时间子类型
|
|
70
|
+
export type TimeSubType = 'year-month' | 'year-month-day' | 'datetime';
|
|
71
|
+
|
|
72
|
+
// 文件子类型
|
|
73
|
+
export type FileSubType =
|
|
74
|
+
| 'default'
|
|
75
|
+
| 'jpg'
|
|
76
|
+
| 'png'
|
|
77
|
+
| 'svg'
|
|
78
|
+
| 'doc'
|
|
79
|
+
| 'ppt'
|
|
80
|
+
| 'excel'
|
|
81
|
+
| 'txt'
|
|
82
|
+
| 'markdown'
|
|
83
|
+
| 'zip';
|
|
84
|
+
|
|
85
|
+
// 枚举展示样式
|
|
86
|
+
export type EnumDisplayStyle = 'select' | 'checkbox' | 'radio' | 'multi-select';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* AssociationPropertyMetadata 类型定义
|
|
90
|
+
* 包含枚举、时间、文件等扩展属性的元数据
|
|
91
|
+
*/
|
|
92
|
+
export interface AssociationPropertyMetadata {
|
|
93
|
+
/** 子类型(用于 time 和 file 类型),现在是数组 */
|
|
94
|
+
SubType?: (TimeSubType | FileSubType)[];
|
|
95
|
+
/** 枚举值 */
|
|
96
|
+
EnumValues?: (string | number | boolean)[];
|
|
97
|
+
/** 枚举展示样式 */
|
|
98
|
+
EnumDisplayStyle?: EnumDisplayStyle;
|
|
99
|
+
}
|
|
2
100
|
|
|
3
101
|
/**
|
|
4
102
|
* CustomParam 的 Schema 定义
|
|
@@ -10,12 +108,29 @@ export interface CustomParamSchema {
|
|
|
10
108
|
Required?: string[];
|
|
11
109
|
Properties?: Record<string, CustomParamSchema>;
|
|
12
110
|
Items?: CustomParamSchema;
|
|
111
|
+
// 排序字段(支持小写)
|
|
112
|
+
order?: number;
|
|
113
|
+
// 排序字段(支持大写,兼容实际数据格式)
|
|
114
|
+
Order?: string | number;
|
|
115
|
+
// 关联属性元数据(包含 SubType、EnumValues、EnumDisplayStyle)
|
|
116
|
+
AssociationPropertyMetadata?: AssociationPropertyMetadata;
|
|
117
|
+
AssociationProperty?: string;
|
|
118
|
+
|
|
119
|
+
// ============ 以下字段已废弃,保留用于向后兼容 ============
|
|
120
|
+
/** @deprecated 使用 AssociationPropertyMetadata.SubType 代替 */
|
|
121
|
+
TimeSubType?: TimeSubType;
|
|
122
|
+
/** @deprecated 使用 AssociationPropertyMetadata.SubType 代替 */
|
|
123
|
+
FileSubType?: FileSubType;
|
|
124
|
+
/** @deprecated 使用 AssociationPropertyMetadata.EnumValues 代替 */
|
|
125
|
+
EnumValues?: string[];
|
|
126
|
+
/** @deprecated 使用 AssociationPropertyMetadata.EnumDisplayStyle 代替 */
|
|
127
|
+
EnumDisplayStyle?: EnumDisplayStyle;
|
|
13
128
|
}
|
|
14
129
|
|
|
15
130
|
/**
|
|
16
131
|
* CustomParamsRenderer 组件的 Props
|
|
17
132
|
*/
|
|
18
|
-
export interface CustomParamsRendererProps {
|
|
133
|
+
export interface CustomParamsRendererProps extends UploadConfig {
|
|
19
134
|
/** CustomParams 的 schema */
|
|
20
135
|
schema: CustomParamSchema;
|
|
21
136
|
/** 表单值 */
|
|
@@ -33,7 +148,7 @@ export interface CustomParamsRendererProps {
|
|
|
33
148
|
/**
|
|
34
149
|
* 单个字段渲染器的 Props
|
|
35
150
|
*/
|
|
36
|
-
export interface FieldRendererProps {
|
|
151
|
+
export interface FieldRendererProps extends UploadConfig {
|
|
37
152
|
/** 字段名 */
|
|
38
153
|
name: string;
|
|
39
154
|
/** 字段 Schema */
|
|
@@ -52,12 +167,14 @@ export interface FieldRendererProps {
|
|
|
52
167
|
errors?: Record<string, string>;
|
|
53
168
|
/** 字段路径(用于匹配错误信息) */
|
|
54
169
|
fieldPath?: string;
|
|
170
|
+
/** 是否隐藏标签(用于数组项渲染时隐藏 Items 标题) */
|
|
171
|
+
hideLabel?: boolean;
|
|
55
172
|
}
|
|
56
173
|
|
|
57
174
|
/**
|
|
58
175
|
* 数组字段的 Props
|
|
59
176
|
*/
|
|
60
|
-
export interface ArrayFieldProps {
|
|
177
|
+
export interface ArrayFieldProps extends UploadConfig {
|
|
61
178
|
/** 字段名 */
|
|
62
179
|
name: string;
|
|
63
180
|
/** 字段 Schema */
|
|
@@ -81,7 +198,7 @@ export interface ArrayFieldProps {
|
|
|
81
198
|
/**
|
|
82
199
|
* 对象字段的 Props
|
|
83
200
|
*/
|
|
84
|
-
export interface ObjectFieldProps {
|
|
201
|
+
export interface ObjectFieldProps extends UploadConfig {
|
|
85
202
|
/** 字段名 */
|
|
86
203
|
name: string;
|
|
87
204
|
/** 字段 Schema */
|
|
@@ -102,6 +219,60 @@ export interface ObjectFieldProps {
|
|
|
102
219
|
fieldPath?: string;
|
|
103
220
|
}
|
|
104
221
|
|
|
222
|
+
/**
|
|
223
|
+
* 时间字段的 Props
|
|
224
|
+
*/
|
|
225
|
+
export interface TimeFieldProps {
|
|
226
|
+
/** 字段名 */
|
|
227
|
+
name: string;
|
|
228
|
+
/** 字段 Schema */
|
|
229
|
+
schema: CustomParamSchema;
|
|
230
|
+
/** 字段值 */
|
|
231
|
+
value?: string;
|
|
232
|
+
/** 值变化回调 */
|
|
233
|
+
onChange?: (value: string | null) => void;
|
|
234
|
+
/** 是否必填 */
|
|
235
|
+
required?: boolean;
|
|
236
|
+
/** 是否禁用 */
|
|
237
|
+
disabled?: boolean;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* 文件字段的 Props
|
|
242
|
+
*/
|
|
243
|
+
export interface FileFieldProps extends UploadConfig {
|
|
244
|
+
/** 字段名 */
|
|
245
|
+
name: string;
|
|
246
|
+
/** 字段 Schema */
|
|
247
|
+
schema: CustomParamSchema;
|
|
248
|
+
/** 字段值 */
|
|
249
|
+
value?: any;
|
|
250
|
+
/** 值变化回调 */
|
|
251
|
+
onChange?: (value: any) => void;
|
|
252
|
+
/** 是否必填 */
|
|
253
|
+
required?: boolean;
|
|
254
|
+
/** 是否禁用 */
|
|
255
|
+
disabled?: boolean;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* 枚举字段的 Props
|
|
260
|
+
*/
|
|
261
|
+
export interface EnumFieldProps {
|
|
262
|
+
/** 字段名 */
|
|
263
|
+
name: string;
|
|
264
|
+
/** 字段 Schema */
|
|
265
|
+
schema: CustomParamSchema;
|
|
266
|
+
/** 字段值 */
|
|
267
|
+
value?: any;
|
|
268
|
+
/** 值变化回调 */
|
|
269
|
+
onChange?: (value: any) => void;
|
|
270
|
+
/** 是否必填 */
|
|
271
|
+
required?: boolean;
|
|
272
|
+
/** 是否禁用 */
|
|
273
|
+
disabled?: boolean;
|
|
274
|
+
}
|
|
275
|
+
|
|
105
276
|
/**
|
|
106
277
|
* 校验错误信息
|
|
107
278
|
*/
|
|
@@ -150,6 +321,12 @@ export const validateCustomParams = (
|
|
|
150
321
|
field: fieldName,
|
|
151
322
|
message: `${fieldSchema?.Title || key} 是必填项`,
|
|
152
323
|
});
|
|
324
|
+
} else if (Array.isArray(fieldValue) && fieldValue.length === 0) {
|
|
325
|
+
// 数组类型的必填检查
|
|
326
|
+
errors.push({
|
|
327
|
+
field: fieldName,
|
|
328
|
+
message: `${fieldSchema?.Title || key} 是必填项`,
|
|
329
|
+
});
|
|
153
330
|
}
|
|
154
331
|
}
|
|
155
332
|
|
|
@@ -194,6 +371,26 @@ export const validateCustomParams = (
|
|
|
194
371
|
}
|
|
195
372
|
});
|
|
196
373
|
}
|
|
374
|
+
|
|
375
|
+
// 校验时间类型
|
|
376
|
+
if (fieldSchema?.Type === 'time' && isRequired) {
|
|
377
|
+
if (!fieldValue) {
|
|
378
|
+
errors.push({
|
|
379
|
+
field: fieldName,
|
|
380
|
+
message: `${fieldSchema?.Title || key} 是必填项`,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// 校验文件类型
|
|
386
|
+
if (fieldSchema?.Type === 'file' && isRequired) {
|
|
387
|
+
if (!fieldValue || (Array.isArray(fieldValue) && fieldValue.length === 0)) {
|
|
388
|
+
errors.push({
|
|
389
|
+
field: fieldName,
|
|
390
|
+
message: `${fieldSchema?.Title || key} 是必填项`,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
197
394
|
});
|
|
198
395
|
|
|
199
396
|
return {
|
|
@@ -201,3 +398,32 @@ export const validateCustomParams = (
|
|
|
201
398
|
errors,
|
|
202
399
|
};
|
|
203
400
|
};
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* 根据 Order 字段对属性进行排序
|
|
404
|
+
* 完全兼容没有 Order 字段的历史数据
|
|
405
|
+
*
|
|
406
|
+
* @param properties - 属性对象
|
|
407
|
+
* @returns 排序后的属性数组 [key, schema][]
|
|
408
|
+
*/
|
|
409
|
+
export const sortPropertiesByOrder = (
|
|
410
|
+
properties: Record<string, CustomParamSchema>
|
|
411
|
+
): [string, CustomParamSchema][] => {
|
|
412
|
+
return Object.entries(properties).sort(([, schemaA], [, schemaB]) => {
|
|
413
|
+
// 读取 Order 字段(支持大小写)
|
|
414
|
+
const orderA = schemaA.Order ?? schemaA.order;
|
|
415
|
+
const orderB = schemaB.Order ?? schemaB.order;
|
|
416
|
+
|
|
417
|
+
// 转换为数字(字符串 "12" -> 12)
|
|
418
|
+
const numA = orderA !== undefined ? Number(orderA) : Number.MAX_SAFE_INTEGER;
|
|
419
|
+
const numB = orderB !== undefined ? Number(orderB) : Number.MAX_SAFE_INTEGER;
|
|
420
|
+
|
|
421
|
+
// 如果两个都没有 Order,保持原有顺序(返回 0)
|
|
422
|
+
// 这样可以确保历史数据(所有字段都没有 Order)不会被打乱
|
|
423
|
+
if (numA === Number.MAX_SAFE_INTEGER && numB === Number.MAX_SAFE_INTEGER) {
|
|
424
|
+
return 0;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return numA - numB;
|
|
428
|
+
});
|
|
429
|
+
};
|
|
@@ -36,12 +36,8 @@ const StatusText = styled.div`
|
|
|
36
36
|
// ==================== Types ====================
|
|
37
37
|
|
|
38
38
|
export interface HistoryCardProps {
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
/** 表单值 */
|
|
42
|
-
formValues?: Record<string, any>;
|
|
43
|
-
/** 表单 Schema */
|
|
44
|
-
formSchema?: CustomParamSchema;
|
|
39
|
+
/** 消息数据对象 */
|
|
40
|
+
data: any;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
/**
|
|
@@ -68,7 +64,35 @@ export const convertSchemaToUpperCase = (schema: any): CustomParamSchema | undef
|
|
|
68
64
|
result.Required = schema.required;
|
|
69
65
|
}
|
|
70
66
|
|
|
71
|
-
|
|
67
|
+
// 排序字段
|
|
68
|
+
if (schema.order !== undefined) {
|
|
69
|
+
result.order = schema.order;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 处理 AssociationPropertyMetadata
|
|
73
|
+
if (schema.associationPropertyMetadata) {
|
|
74
|
+
const metadata = schema.associationPropertyMetadata;
|
|
75
|
+
result.AssociationPropertyMetadata = {};
|
|
76
|
+
|
|
77
|
+
// SubType(数组格式)
|
|
78
|
+
if (metadata.subType) {
|
|
79
|
+
const subType = metadata.subType;
|
|
80
|
+
// 确保是数组格式
|
|
81
|
+
result.AssociationPropertyMetadata.SubType = Array.isArray(subType) ? subType : [subType];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// EnumValues
|
|
85
|
+
if (metadata.enumValues) {
|
|
86
|
+
result.AssociationPropertyMetadata.EnumValues = metadata.enumValues;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// EnumDisplayStyle
|
|
90
|
+
if (metadata.enumDisplayStyle) {
|
|
91
|
+
result.AssociationPropertyMetadata.EnumDisplayStyle = metadata.enumDisplayStyle;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if ((schema.properties && typeof schema.properties === 'object')) {
|
|
72
96
|
result.Properties = {};
|
|
73
97
|
for (const [key, value] of Object.entries(schema.properties)) {
|
|
74
98
|
const converted = convertSchemaToUpperCase(value);
|
|
@@ -88,21 +112,15 @@ export const convertSchemaToUpperCase = (schema: any): CustomParamSchema | undef
|
|
|
88
112
|
/**
|
|
89
113
|
* HistoryCard 历史卡片组件 (SDK 版本)
|
|
90
114
|
* 用于展示历史对话中的 card 类型消息(只读模式)
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```tsx
|
|
94
|
-
* <HistoryCard
|
|
95
|
-
* approvalStatus="approved"
|
|
96
|
-
* formValues={{ name: 'test', age: 18 }}
|
|
97
|
-
* formSchema={schema}
|
|
98
|
-
* />
|
|
99
|
-
* ```
|
|
100
115
|
*/
|
|
101
|
-
export const HistoryCard: React.FC<HistoryCardProps> = ({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
116
|
+
export const HistoryCard: React.FC<HistoryCardProps> = ({ data }) => {
|
|
117
|
+
// 从data中提取需要的参数
|
|
118
|
+
const approvalStatus = data?.approvalStatus;
|
|
119
|
+
|
|
120
|
+
// 使用测试数据或真实数据
|
|
121
|
+
const formValues = (data?.formValues || {});
|
|
122
|
+
const formSchema = data?.formSchema;
|
|
123
|
+
|
|
106
124
|
// 判断是否已提交
|
|
107
125
|
const isApproved = approvalStatus === 'approved';
|
|
108
126
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { Button, message } from 'antd';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import CustomParamsRenderer, { validateCustomParams,
|
|
4
|
+
import CustomParamsRenderer, { validateCustomParams, UploadSender, FileUploader } from './CustomParamsRenderer';
|
|
5
5
|
|
|
6
6
|
// ==================== Styled Components ====================
|
|
7
7
|
|
|
@@ -35,16 +35,12 @@ const StatusText = styled.div`
|
|
|
35
35
|
// ==================== Types ====================
|
|
36
36
|
|
|
37
37
|
export interface HumanVerifyProps {
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
/** CustomParams 的 schema */
|
|
45
|
-
customParamsSchema?: CustomParamSchema;
|
|
46
|
-
/** CustomParams 的 key(用于提交时的字段名) */
|
|
47
|
-
customParamsKey?: string;
|
|
38
|
+
/** 消息数据对象 */
|
|
39
|
+
data: any;
|
|
40
|
+
/** 上传发送方法 */
|
|
41
|
+
uploadSender?: UploadSender;
|
|
42
|
+
/** 文件上传方法 */
|
|
43
|
+
fileUploader?: FileUploader;
|
|
48
44
|
/** 提交回调函数 */
|
|
49
45
|
onSubmit?: (data: {
|
|
50
46
|
verifyId: string;
|
|
@@ -58,39 +54,20 @@ export interface HumanVerifyProps {
|
|
|
58
54
|
/**
|
|
59
55
|
* HumanVerify 人工审核组件 (SDK 版本)
|
|
60
56
|
* 用于展示需要人工审核的表单,并处理提交逻辑
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```tsx
|
|
64
|
-
* <HumanVerify
|
|
65
|
-
* verifyId="xxx"
|
|
66
|
-
* sessionWebhook="https://..."
|
|
67
|
-
* approved={false}
|
|
68
|
-
* customParamsSchema={schema}
|
|
69
|
-
* customParamsKey="customParams"
|
|
70
|
-
* onSubmit={(data) => {
|
|
71
|
-
* bot.postMessage({
|
|
72
|
-
* msgType: 'cardCallBack',
|
|
73
|
-
* data: {
|
|
74
|
-
* sessionWebhook: data.sessionWebhook,
|
|
75
|
-
* content: JSON.stringify({
|
|
76
|
-
* verifyId: data.verifyId,
|
|
77
|
-
* status: data.status,
|
|
78
|
-
* [data.customParamsKey]: data.customParamsValue,
|
|
79
|
-
* }),
|
|
80
|
-
* },
|
|
81
|
-
* });
|
|
82
|
-
* }}
|
|
83
|
-
* />
|
|
84
|
-
* ```
|
|
85
57
|
*/
|
|
86
|
-
export const HumanVerify: React.FC<HumanVerifyProps> = ({
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
customParamsKey = 'customParams',
|
|
92
|
-
onSubmit,
|
|
58
|
+
export const HumanVerify: React.FC<HumanVerifyProps> = ({
|
|
59
|
+
data,
|
|
60
|
+
uploadSender,
|
|
61
|
+
fileUploader,
|
|
62
|
+
onSubmit
|
|
93
63
|
}) => {
|
|
64
|
+
// 从 data 中提取需要的参数
|
|
65
|
+
const verifyId = data?.verifyId;
|
|
66
|
+
const sessionWebhook = data?.sessionWebhook;
|
|
67
|
+
const approved = data?.approved || false;
|
|
68
|
+
const customParamsSchema = data?.customParams;
|
|
69
|
+
const customParamsKey = data?.customParamsKey;
|
|
70
|
+
|
|
94
71
|
// CustomParams表单状态管理
|
|
95
72
|
const [customParamsValue, setCustomParamsValue] = useState<Record<string, any>>({});
|
|
96
73
|
// CustomParams验证错误状态
|
|
@@ -142,7 +119,7 @@ export const HumanVerify: React.FC<HumanVerifyProps> = ({
|
|
|
142
119
|
}
|
|
143
120
|
|
|
144
121
|
// 调用提交回调
|
|
145
|
-
onSubmit({
|
|
122
|
+
onSubmit?.({
|
|
146
123
|
verifyId,
|
|
147
124
|
sessionWebhook: sessionWebhook || '',
|
|
148
125
|
status: 'approve',
|
|
@@ -159,7 +136,8 @@ export const HumanVerify: React.FC<HumanVerifyProps> = ({
|
|
|
159
136
|
value={customParamsValue}
|
|
160
137
|
onChange={setCustomParamsValue}
|
|
161
138
|
errors={validationErrors}
|
|
162
|
-
|
|
139
|
+
uploadSender={uploadSender}
|
|
140
|
+
fileUploader={fileUploader}
|
|
163
141
|
/>
|
|
164
142
|
)}
|
|
165
143
|
<StatusContainer $approved={approved}>
|
|
@@ -181,4 +159,4 @@ export const HumanVerify: React.FC<HumanVerifyProps> = ({
|
|
|
181
159
|
);
|
|
182
160
|
};
|
|
183
161
|
|
|
184
|
-
export default HumanVerify;
|
|
162
|
+
export default HumanVerify;
|
|
@@ -351,11 +351,7 @@ export const MessageBubble: React.FC<MessageBubbleProps> = ({
|
|
|
351
351
|
{/* HumanVerify事件 - 人工审核表单 */}
|
|
352
352
|
{eventType === 'humanVerify' && humanVerifyData && (
|
|
353
353
|
<HumanVerify
|
|
354
|
-
|
|
355
|
-
sessionWebhook={humanVerifyData.sessionWebhook}
|
|
356
|
-
approved={humanVerifyData.approved}
|
|
357
|
-
customParamsSchema={humanVerifyData.customParams}
|
|
358
|
-
customParamsKey={humanVerifyData.customParamsKey}
|
|
354
|
+
data={humanVerifyData}
|
|
359
355
|
onSubmit={onHumanVerifySubmit}
|
|
360
356
|
/>
|
|
361
357
|
)}
|
|
@@ -363,14 +359,12 @@ export const MessageBubble: React.FC<MessageBubbleProps> = ({
|
|
|
363
359
|
{/* HistoryCard 事件 - 历史对话中的审核卡片 */}
|
|
364
360
|
{eventType === 'historyCard' && historyCardData && (
|
|
365
361
|
<HistoryCard
|
|
366
|
-
|
|
367
|
-
formValues={historyCardData.formValues}
|
|
368
|
-
formSchema={historyCardData.formSchema}
|
|
362
|
+
data={historyCardData}
|
|
369
363
|
/>
|
|
370
364
|
)}
|
|
371
365
|
|
|
372
366
|
{/* 参考资料 */}
|
|
373
|
-
{references.length > 0 && status === 'Success' && (
|
|
367
|
+
{references && references.length > 0 && status === 'Success' && (
|
|
374
368
|
<ReferencesContainer>
|
|
375
369
|
<DocReferences
|
|
376
370
|
items={references}
|
|
@@ -397,4 +391,4 @@ export const MessageBubble: React.FC<MessageBubbleProps> = ({
|
|
|
397
391
|
);
|
|
398
392
|
};
|
|
399
393
|
|
|
400
|
-
export default MessageBubble;
|
|
394
|
+
export default MessageBubble;
|
|
@@ -254,7 +254,7 @@ export const RichMessageBubble: React.FC<RichMessageBubbleProps> = ({
|
|
|
254
254
|
role="bot"
|
|
255
255
|
>
|
|
256
256
|
{/* 参考资料 */}
|
|
257
|
-
{references.length > 0 && status === 'Success' && (
|
|
257
|
+
{references && references.length > 0 && status === 'Success' && (
|
|
258
258
|
<ReferencesContainer>
|
|
259
259
|
<DocReferences
|
|
260
260
|
items={references}
|
|
@@ -280,4 +280,4 @@ export const RichMessageBubble: React.FC<RichMessageBubbleProps> = ({
|
|
|
280
280
|
);
|
|
281
281
|
};
|
|
282
282
|
|
|
283
|
-
export default RichMessageBubble;
|
|
283
|
+
export default RichMessageBubble;
|
package/src/index.ts
CHANGED