@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
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import React, { useCallback, useContext } from 'react';
|
|
2
|
-
import { Input, InputNumber, Switch
|
|
3
|
-
import
|
|
4
|
-
import { FieldRendererProps } from './types';
|
|
1
|
+
import React, { useCallback, useContext, useMemo } from 'react';
|
|
2
|
+
import { ConfigProvider, Input, InputNumber, Switch } from 'antd';
|
|
3
|
+
import { FieldRendererProps, CustomParamSchema } from './types';
|
|
5
4
|
import { ArrayField } from './ArrayField';
|
|
6
5
|
import { ObjectField } from './ObjectField';
|
|
6
|
+
import { EnumField } from './EnumField';
|
|
7
|
+
import styled from 'styled-components';
|
|
8
|
+
import TimeField from './TimeField';
|
|
9
|
+
import FileField from './FileField';
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
// ==================== Styled Components ====================
|
|
9
13
|
|
|
@@ -45,6 +49,42 @@ const FieldError = styled.div`
|
|
|
45
49
|
margin-top: 4px;
|
|
46
50
|
`;
|
|
47
51
|
|
|
52
|
+
// 数组字段容器(用于多选枚举数组)
|
|
53
|
+
const ArrayFieldContainer = styled.div`
|
|
54
|
+
border: 1px solid #dbdbdb;
|
|
55
|
+
border-radius: 10px;
|
|
56
|
+
padding: 24px 16px;
|
|
57
|
+
position: relative;
|
|
58
|
+
margin-top: 20px;
|
|
59
|
+
margin-bottom: 20px;
|
|
60
|
+
background-color: #fff;
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
// 数组标题
|
|
64
|
+
const ArrayTitle = styled.div`
|
|
65
|
+
position: absolute;
|
|
66
|
+
top: -12px;
|
|
67
|
+
left: 15px;
|
|
68
|
+
background: #fff;
|
|
69
|
+
padding: 2px 10px;
|
|
70
|
+
white-space: nowrap;
|
|
71
|
+
text-overflow: ellipsis;
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
word-break: break-all;
|
|
74
|
+
max-width: calc(100% - 30px);
|
|
75
|
+
font-size: 14px;
|
|
76
|
+
font-weight: 500;
|
|
77
|
+
color: #1f2329;
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
// 数组描述
|
|
81
|
+
const ArrayDescription = styled.div`
|
|
82
|
+
font-size: 12px;
|
|
83
|
+
color: #8f959e;
|
|
84
|
+
margin-bottom: 12px;
|
|
85
|
+
word-break: break-word;
|
|
86
|
+
`;
|
|
87
|
+
|
|
48
88
|
/**
|
|
49
89
|
* InputWrapper 组件
|
|
50
90
|
* 支持动态 prefixCls,自动继承用户项目的 ConfigProvider 配置
|
|
@@ -61,6 +101,15 @@ const InputWrapper = styled.div<{ $prefixCls: string }>`
|
|
|
61
101
|
}
|
|
62
102
|
`;
|
|
63
103
|
|
|
104
|
+
/**
|
|
105
|
+
* 判断是否有枚举值
|
|
106
|
+
* 优先从 AssociationPropertyMetadata 中读取,兼容旧的 EnumValues 字段
|
|
107
|
+
*/
|
|
108
|
+
const hasEnumValues = (schema: CustomParamSchema): boolean => {
|
|
109
|
+
const enumValues = schema.AssociationPropertyMetadata?.EnumValues || schema.EnumValues;
|
|
110
|
+
return Array.isArray(enumValues) && enumValues.length > 0;
|
|
111
|
+
};
|
|
112
|
+
|
|
64
113
|
/**
|
|
65
114
|
* 单个字段渲染器
|
|
66
115
|
* 根据字段类型渲染对应的输入组件
|
|
@@ -75,6 +124,9 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
75
124
|
level = 0,
|
|
76
125
|
errors = {},
|
|
77
126
|
fieldPath = '',
|
|
127
|
+
uploadSender,
|
|
128
|
+
fileUploader,
|
|
129
|
+
hideLabel = false,
|
|
78
130
|
}) => {
|
|
79
131
|
const { Type, Title, Description } = schema;
|
|
80
132
|
const displayTitle = Title || name;
|
|
@@ -97,8 +149,25 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
97
149
|
[onChange]
|
|
98
150
|
);
|
|
99
151
|
|
|
152
|
+
// 判断是否为枚举类型
|
|
153
|
+
const isEnum = useMemo(() => hasEnumValues(schema), [schema]);
|
|
154
|
+
|
|
100
155
|
// 渲染基础类型输入框
|
|
101
156
|
const renderInput = () => {
|
|
157
|
+
// 优先处理枚举类型
|
|
158
|
+
if (isEnum) {
|
|
159
|
+
return (
|
|
160
|
+
<EnumField
|
|
161
|
+
name={name}
|
|
162
|
+
schema={schema}
|
|
163
|
+
value={value}
|
|
164
|
+
onChange={handleChange}
|
|
165
|
+
required={required}
|
|
166
|
+
disabled={disabled}
|
|
167
|
+
/>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
102
171
|
switch (Type) {
|
|
103
172
|
case 'string':
|
|
104
173
|
return (
|
|
@@ -107,6 +176,7 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
107
176
|
value={value}
|
|
108
177
|
onChange={(e) => handleChange(e.target.value)}
|
|
109
178
|
disabled={disabled}
|
|
179
|
+
placeholder={`请输入${displayTitle}`}
|
|
110
180
|
/>
|
|
111
181
|
</InputWrapper>
|
|
112
182
|
);
|
|
@@ -119,6 +189,7 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
119
189
|
onChange={handleChange}
|
|
120
190
|
disabled={disabled}
|
|
121
191
|
style={{ width: '100%' }}
|
|
192
|
+
placeholder={`请输入${displayTitle}`}
|
|
122
193
|
/>
|
|
123
194
|
</InputWrapper>
|
|
124
195
|
);
|
|
@@ -126,14 +197,75 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
126
197
|
case 'boolean':
|
|
127
198
|
return (
|
|
128
199
|
<Switch
|
|
129
|
-
style={{borderRadius: 16}}
|
|
200
|
+
style={{ borderRadius: 16 }}
|
|
130
201
|
checked={value}
|
|
131
202
|
onChange={handleChange}
|
|
132
203
|
disabled={disabled}
|
|
133
204
|
/>
|
|
134
205
|
);
|
|
135
206
|
|
|
136
|
-
case '
|
|
207
|
+
case 'time':
|
|
208
|
+
return (
|
|
209
|
+
<TimeField
|
|
210
|
+
name={name}
|
|
211
|
+
schema={schema}
|
|
212
|
+
value={value}
|
|
213
|
+
onChange={handleChange}
|
|
214
|
+
required={required}
|
|
215
|
+
disabled={disabled}
|
|
216
|
+
/>
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
case 'file':
|
|
220
|
+
return (
|
|
221
|
+
<FileField
|
|
222
|
+
name={name}
|
|
223
|
+
schema={schema}
|
|
224
|
+
value={value}
|
|
225
|
+
onChange={handleChange}
|
|
226
|
+
required={required}
|
|
227
|
+
disabled={disabled}
|
|
228
|
+
uploadSender={uploadSender}
|
|
229
|
+
fileUploader={fileUploader}
|
|
230
|
+
/>
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
case 'array': {
|
|
234
|
+
// 检查是否为多选枚举类型的数组(multi-select 或 checkbox)
|
|
235
|
+
// 这种情况下,数组本身就是多选的结果,不需要再套一层数组逻辑
|
|
236
|
+
const itemsSchema = schema?.Items;
|
|
237
|
+
const itemsEnumValues = itemsSchema?.AssociationPropertyMetadata?.EnumValues;
|
|
238
|
+
const itemsEnumDisplayStyle = itemsSchema?.AssociationPropertyMetadata?.EnumDisplayStyle;
|
|
239
|
+
const isMultiSelectEnumArray = Array.isArray(itemsEnumValues) && itemsEnumValues.length > 0 &&
|
|
240
|
+
(itemsEnumDisplayStyle === 'multi-select' || itemsEnumDisplayStyle === 'checkbox');
|
|
241
|
+
|
|
242
|
+
if (isMultiSelectEnumArray && itemsSchema) {
|
|
243
|
+
// 使用数组样式外框包裹 EnumField,保持数组的视觉一致性
|
|
244
|
+
// 但不渲染增加/删除按钮,因为多选组件本身已经支持多选
|
|
245
|
+
return (
|
|
246
|
+
<ArrayFieldContainer>
|
|
247
|
+
<ArrayTitle>
|
|
248
|
+
{required && <Required>*</Required>}
|
|
249
|
+
<span>{displayTitle}</span>
|
|
250
|
+
</ArrayTitle>
|
|
251
|
+
{Description && (
|
|
252
|
+
<ArrayDescription>{Description}</ArrayDescription>
|
|
253
|
+
)}
|
|
254
|
+
<EnumField
|
|
255
|
+
name={name}
|
|
256
|
+
schema={{
|
|
257
|
+
...itemsSchema,
|
|
258
|
+
Title: schema.Title || itemsSchema.Title,
|
|
259
|
+
}}
|
|
260
|
+
value={value}
|
|
261
|
+
onChange={handleChange}
|
|
262
|
+
required={required}
|
|
263
|
+
disabled={disabled}
|
|
264
|
+
/>
|
|
265
|
+
</ArrayFieldContainer>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
137
269
|
return (
|
|
138
270
|
<ArrayField
|
|
139
271
|
name={name}
|
|
@@ -145,8 +277,11 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
145
277
|
level={level}
|
|
146
278
|
errors={errors}
|
|
147
279
|
fieldPath={fieldPath}
|
|
280
|
+
uploadSender={uploadSender}
|
|
281
|
+
fileUploader={fileUploader}
|
|
148
282
|
/>
|
|
149
283
|
);
|
|
284
|
+
}
|
|
150
285
|
|
|
151
286
|
case 'object':
|
|
152
287
|
return (
|
|
@@ -160,6 +295,8 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
160
295
|
level={level}
|
|
161
296
|
errors={errors}
|
|
162
297
|
fieldPath={fieldPath}
|
|
298
|
+
uploadSender={uploadSender}
|
|
299
|
+
fileUploader={fileUploader}
|
|
163
300
|
/>
|
|
164
301
|
);
|
|
165
302
|
|
|
@@ -170,17 +307,24 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
170
307
|
value={value}
|
|
171
308
|
onChange={(e) => handleChange(e.target.value)}
|
|
172
309
|
disabled={disabled}
|
|
310
|
+
placeholder={`请输入${displayTitle}`}
|
|
173
311
|
/>
|
|
174
312
|
</InputWrapper>
|
|
175
313
|
);
|
|
176
314
|
}
|
|
177
315
|
};
|
|
178
316
|
|
|
179
|
-
// 对于 object 和 array
|
|
317
|
+
// 对于 object 和 array 类型(包括多选枚举数组),直接渲染,不需要外层包装
|
|
318
|
+
// 因为它们内部已经有自己的样式容器
|
|
180
319
|
if (Type === 'object' || Type === 'array') {
|
|
181
320
|
return renderInput();
|
|
182
321
|
}
|
|
183
322
|
|
|
323
|
+
// 如果隐藏标签,直接返回输入组件(用于数组项渲染)
|
|
324
|
+
if (hideLabel) {
|
|
325
|
+
return renderInput();
|
|
326
|
+
}
|
|
327
|
+
|
|
184
328
|
// 基础类型渲染带标签的表单项
|
|
185
329
|
return (
|
|
186
330
|
<FieldItem>
|
|
@@ -199,4 +343,4 @@ export const FieldRenderer: React.FC<FieldRendererProps> = ({
|
|
|
199
343
|
);
|
|
200
344
|
};
|
|
201
345
|
|
|
202
|
-
export default FieldRenderer;
|
|
346
|
+
export default FieldRenderer;
|