@baishuyun/ai-design 1.0.8 → 1.0.9

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.
@@ -0,0 +1,460 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { useState, useCallback } from 'react';
3
+ import { BsConditionInput } from '../components/agent-helper/condition-input';
4
+ import { conditionStringify2bsCondition } from '@baishuyun/ai-feat-utils';
5
+ import type { IField, IFieldValueService, ICondition } from '@baishuyun/types';
6
+
7
+ const mockService: IFieldValueService = {
8
+ searchUsers: async (keyword) => {
9
+ await new Promise((r) => setTimeout(r, 300));
10
+ const users = [
11
+ { id: 'user1', name: '张三' },
12
+ { id: 'user2', name: '李四' },
13
+ { id: 'user3', name: '王五' },
14
+ ];
15
+ return keyword ? users.filter((u) => u.name.includes(keyword)) : users;
16
+ },
17
+ searchDepts: async (keyword) => {
18
+ await new Promise((r) => setTimeout(r, 300));
19
+ const depts = [
20
+ { id: 'dept1', name: '技术部' },
21
+ { id: 'dept2', name: '产品部' },
22
+ { id: 'dept3', name: '设计部' },
23
+ ];
24
+ return keyword ? depts.filter((d) => d.name.includes(keyword)) : depts;
25
+ },
26
+ searchUserGroups: async (keyword) => {
27
+ await new Promise((r) => setTimeout(r, 300));
28
+ const groups = [
29
+ { id: 'ug1', name: '管理组' },
30
+ { id: 'ug2', name: '普通组' },
31
+ ];
32
+ return keyword ? groups.filter((g) => g.name.includes(keyword)) : groups;
33
+ },
34
+ searchDeptGroups: async (keyword) => {
35
+ await new Promise((r) => setTimeout(r, 300));
36
+ const groups = [
37
+ { id: 'dg1', name: '研发中心' },
38
+ { id: 'dg2', name: '销售中心' },
39
+ ];
40
+ return keyword ? groups.filter((g) => g.name.includes(keyword)) : groups;
41
+ },
42
+ searchAddress: async (keyword) => {
43
+ await new Promise((r) => setTimeout(r, 300));
44
+ const addresses = [
45
+ { province: '浙江省', city: '杭州市', district: '西湖区' },
46
+ { province: '北京市', city: '北京市', district: '朝阳区' },
47
+ ];
48
+ return keyword
49
+ ? addresses.filter(
50
+ (a) =>
51
+ a.province.includes(keyword) ||
52
+ a.city.includes(keyword) ||
53
+ a.district.includes(keyword),
54
+ )
55
+ : addresses;
56
+ },
57
+ searchLocation: async (keyword) => {
58
+ await new Promise((r) => setTimeout(r, 300));
59
+ return [
60
+ {
61
+ province: '浙江省',
62
+ city: '杭州市',
63
+ district: '西湖区',
64
+ detail: '文三路 123 号',
65
+ lnglatXY: [120.15, 30.28] as [number, number],
66
+ },
67
+ {
68
+ province: '北京市',
69
+ city: '北京市',
70
+ district: '朝阳区',
71
+ detail: '望京 SOHO',
72
+ lnglatXY: [116.48, 39.99] as [number, number],
73
+ },
74
+ ].filter((l) => !keyword || l.detail.includes(keyword));
75
+ },
76
+ searchDistinctValues: async (_field, keyword) => {
77
+ await new Promise((r) => setTimeout(r, 300));
78
+ const values = [
79
+ { label: '苹果', value: 'apple' },
80
+ { label: '香蕉', value: 'banana' },
81
+ { label: '橙子', value: 'orange' },
82
+ { label: '葡萄', value: 'grape' },
83
+ ];
84
+ return keyword ? values.filter((v) => v.label.includes(keyword)) : values;
85
+ },
86
+ };
87
+
88
+ const mockFields: IField[] = [
89
+ {
90
+ label: '姓名',
91
+ description: '请输入姓名',
92
+ widget: { type: 'text', widgetName: 'text', value: '' },
93
+ },
94
+ {
95
+ label: '年龄',
96
+ description: '请输入年龄',
97
+ widget: { type: 'number', widgetName: 'number', value: '' },
98
+ },
99
+ {
100
+ label: '出生日期',
101
+ description: '请选择出生日期',
102
+ widget: { type: 'datetime', widgetName: 'datetime', value: '' },
103
+ },
104
+ {
105
+ label: '备注',
106
+ description: '请输入备注',
107
+ widget: { type: 'textarea', widgetName: 'textarea', value: '' },
108
+ },
109
+ {
110
+ label: '性别',
111
+ widget: {
112
+ type: 'radiogroup',
113
+ widgetName: 'radiogroup',
114
+ value: '',
115
+ items: [
116
+ { label: '男', value: 'male' },
117
+ { label: '女', value: 'female' },
118
+ ],
119
+ },
120
+ },
121
+ {
122
+ label: '所在城市',
123
+ widget: {
124
+ type: 'combo',
125
+ widgetName: 'combo',
126
+ value: '',
127
+ items: [
128
+ { label: '北京', value: 'beijing' },
129
+ { label: '上海', value: 'shanghai' },
130
+ { label: '广州', value: 'guangzhou' },
131
+ ],
132
+ },
133
+ },
134
+ {
135
+ label: '兴趣爱好',
136
+ widget: {
137
+ type: 'checkboxgroup',
138
+ widgetName: 'checkboxgroup',
139
+ value: [],
140
+ items: [
141
+ { label: '阅读', value: 'reading' },
142
+ { label: '运动', value: 'sports' },
143
+ { label: '音乐', value: 'music' },
144
+ ],
145
+ },
146
+ },
147
+ {
148
+ label: '附件上传',
149
+ widget: { type: 'upload', widgetName: 'upload', value: '' },
150
+ },
151
+ {
152
+ label: '负责人',
153
+ widget: { type: 'user', widgetName: 'user', value: '' },
154
+ },
155
+ {
156
+ label: '所属部门',
157
+ widget: { type: 'dept', widgetName: 'dept', value: '' },
158
+ },
159
+ {
160
+ label: '密码',
161
+ widget: { type: 'password', widgetName: 'password', value: '' },
162
+ },
163
+ {
164
+ label: '性别(单选)',
165
+ widget: {
166
+ type: 'radio',
167
+ widgetName: 'radio',
168
+ value: '',
169
+ items: [
170
+ { label: '男', value: 'male' },
171
+ { label: '女', value: 'female' },
172
+ ],
173
+ },
174
+ },
175
+ {
176
+ label: '下拉多选',
177
+ widget: {
178
+ type: 'combocheck',
179
+ widgetName: 'combocheck',
180
+ value: [],
181
+ items: [
182
+ { label: '选项A', value: 'a' },
183
+ { label: '选项B', value: 'b' },
184
+ { label: '选项C', value: 'c' },
185
+ ],
186
+ },
187
+ },
188
+ {
189
+ label: '地址',
190
+ widget: { type: 'address', widgetName: 'address', value: {} },
191
+ },
192
+ {
193
+ label: '位置',
194
+ widget: { type: 'location', widgetName: 'location', value: {} },
195
+ },
196
+ {
197
+ label: '流水号',
198
+ widget: { type: 'sn', widgetName: 'sn', value: '' },
199
+ },
200
+ {
201
+ label: '用户组',
202
+ widget: { type: 'usergroup', widgetName: 'usergroup', value: '' },
203
+ },
204
+ {
205
+ label: '部门组',
206
+ widget: { type: 'deptgroup', widgetName: 'deptgroup', value: '' },
207
+ },
208
+ {
209
+ label: '图片',
210
+ widget: { type: 'image', widgetName: 'image', value: '' },
211
+ },
212
+ {
213
+ label: '联动数据',
214
+ widget: { type: 'linkdata', widgetName: 'linkdata', value: '' },
215
+ },
216
+ {
217
+ label: '流程状态',
218
+ widget: { type: 'flowState', widgetName: 'flowState', value: '' },
219
+ },
220
+ {
221
+ label: '签名',
222
+ widget: { type: 'signature', widgetName: 'signature', value: '' },
223
+ },
224
+ ];
225
+
226
+ function makeBSString(cond: ICondition): string {
227
+ return conditionStringify2bsCondition(cond);
228
+ }
229
+
230
+ const meta: Meta<typeof BsConditionInput> = {
231
+ title: 'Agent Helper/BsConditionInput',
232
+ component: BsConditionInput,
233
+ tags: ['autodocs'],
234
+ parameters: {
235
+ layout: 'centered',
236
+ },
237
+ args: {
238
+ targetName: '流程结束 或 流程节点',
239
+ fields: mockFields,
240
+ disabled: false,
241
+ },
242
+ decorators: [
243
+ (Story) => (
244
+ <div style={{ width: '960px' }}>
245
+ <Story />
246
+ </div>
247
+ ),
248
+ ],
249
+ };
250
+
251
+ export default meta;
252
+ type Story = StoryObj<typeof meta>;
253
+
254
+ export const Empty: Story = {
255
+ args: {
256
+ targetName: '流程结束 或 流程节点',
257
+ fields: mockFields,
258
+ },
259
+ };
260
+
261
+ export const WithConditions: Story = {
262
+ args: {
263
+ targetName: '流程结束 或 流程节点',
264
+ fields: mockFields,
265
+ defaultValue: makeBSString({
266
+ targetName: '流程结束 或 流程节点',
267
+ quantifier: 'all',
268
+ items: [
269
+ {
270
+ id: 'item-1',
271
+ field: mockFields[0],
272
+ operator: 'contains',
273
+ value: '张三',
274
+ },
275
+ {
276
+ id: 'item-2',
277
+ field: mockFields[1],
278
+ operator: 'gte',
279
+ value: 18,
280
+ },
281
+ ],
282
+ }),
283
+ },
284
+ };
285
+
286
+ export const WithDeleteAll: Story = {
287
+ args: {
288
+ targetName: '流程结束 或 流程节点',
289
+ fields: mockFields,
290
+ defaultValue: makeBSString({
291
+ targetName: '流程结束 或 流程节点',
292
+ quantifier: 'any',
293
+ items: [
294
+ {
295
+ id: 'item-1',
296
+ field: mockFields[0],
297
+ operator: 'contains',
298
+ value: '张三',
299
+ },
300
+ {
301
+ id: 'item-2',
302
+ field: mockFields[1],
303
+ operator: 'gte',
304
+ value: 18,
305
+ },
306
+ {
307
+ id: 'item-3',
308
+ field: mockFields[5],
309
+ operator: 'in',
310
+ value: ['beijing', 'shanghai'],
311
+ },
312
+ {
313
+ id: 'item-4',
314
+ field: mockFields[2],
315
+ operator: 'range',
316
+ value: undefined,
317
+ },
318
+ ],
319
+ }),
320
+ },
321
+ };
322
+
323
+ export const Controlled: Story = {
324
+ render: () => {
325
+ const [bsString, setBsString] = useState<string>(
326
+ makeBSString({
327
+ targetName: '流程结束 或 流程节点',
328
+ quantifier: 'all',
329
+ items: [
330
+ {
331
+ id: 'item-1',
332
+ field: mockFields[0],
333
+ operator: 'contains',
334
+ value: '张三',
335
+ },
336
+ {
337
+ id: 'item-2',
338
+ field: mockFields[1],
339
+ operator: 'gte',
340
+ value: 18,
341
+ },
342
+ ],
343
+ }),
344
+ );
345
+
346
+ const handleChange = useCallback((newBS: string) => {
347
+ setBsString(newBS);
348
+ }, []);
349
+
350
+ return (
351
+ <div className="flex flex-col gap-[16px]">
352
+ <BsConditionInput
353
+ targetName="流程结束 或 流程节点"
354
+ fields={mockFields}
355
+ value={bsString}
356
+ onChange={handleChange}
357
+ />
358
+ <div className="text-[12px] text-[#666666] bg-[#F5F5F5] rounded-[4px] p-[8px] font-mono">
359
+ <pre>{bsString}</pre>
360
+ </div>
361
+ </div>
362
+ );
363
+ },
364
+ };
365
+
366
+ export const RangeOperators: Story = {
367
+ args: {
368
+ targetName: '流程结束',
369
+ fields: mockFields,
370
+ service: mockService,
371
+ defaultValue: makeBSString({
372
+ targetName: '流程结束',
373
+ quantifier: 'all',
374
+ items: [
375
+ {
376
+ id: 'range-1',
377
+ field: mockFields[1],
378
+ operator: 'range',
379
+ value: { min: 18, max: 60 },
380
+ },
381
+ {
382
+ id: 'range-2',
383
+ field: mockFields[2],
384
+ operator: 'range',
385
+ value: { min: '2020-01-01T00:00', max: '2025-12-31T23:59' },
386
+ },
387
+ ],
388
+ }),
389
+ },
390
+ };
391
+
392
+ export const MixedOperators: Story = {
393
+ args: {
394
+ targetName: '表单数据',
395
+ fields: mockFields,
396
+ service: mockService,
397
+ defaultValue: makeBSString({
398
+ targetName: '表单数据',
399
+ quantifier: 'all',
400
+ items: [
401
+ {
402
+ id: 'mixed-1',
403
+ field: mockFields[0],
404
+ operator: 'contains',
405
+ value: '张',
406
+ },
407
+ {
408
+ id: 'mixed-2',
409
+ field: mockFields[1],
410
+ operator: 'range',
411
+ value: { min: 0, max: 100 },
412
+ },
413
+ {
414
+ id: 'mixed-3',
415
+ field: mockFields[2],
416
+ operator: 'range',
417
+ value: { min: '2025-01-01T00:00', max: '2025-06-30T23:59' },
418
+ },
419
+ {
420
+ id: 'mixed-4',
421
+ field: mockFields[0],
422
+ operator: 'in',
423
+ value: ['orange', 'grape'],
424
+ },
425
+ ],
426
+ }),
427
+ },
428
+ };
429
+
430
+ export const Disabled: Story = {
431
+ args: {
432
+ targetName: '流程结束 或 流程节点',
433
+ fields: mockFields,
434
+ disabled: true,
435
+ defaultValue: makeBSString({
436
+ targetName: '流程结束 或 流程节点',
437
+ quantifier: 'all',
438
+ items: [
439
+ {
440
+ id: 'item-1',
441
+ field: mockFields[0],
442
+ operator: 'contains',
443
+ value: '张三',
444
+ },
445
+ {
446
+ id: 'item-2',
447
+ field: mockFields[1],
448
+ operator: 'gte',
449
+ value: 18,
450
+ },
451
+ {
452
+ id: 'item-3',
453
+ field: mockFields[5],
454
+ operator: 'in',
455
+ value: ['beijing', 'shanghai'],
456
+ },
457
+ ],
458
+ }),
459
+ },
460
+ };
@@ -43,10 +43,8 @@ export const Default: Story = {};
43
43
  export const WithInitialValue: Story = {
44
44
  args: {
45
45
  value: {
46
- dateRange: {
47
- from: subDays(new Date(), 7),
48
- to: new Date(),
49
- },
46
+ startDate: subDays(new Date(), 7),
47
+ endDate: new Date(),
50
48
  triggerType: 'scheduler',
51
49
  execResult: 'success',
52
50
  },