@hzab/flowlong-designer 0.0.1

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,240 @@
1
+ import { useRef, useState, useContext, useEffect } from "react";
2
+ import { Modal, Input, Button, Tree, Checkbox, Pagination, Avatar } from "antd";
3
+ import { RightOutlined, DeleteOutlined } from "@ant-design/icons";
4
+
5
+ import { SelectContext } from "./SelectContext";
6
+
7
+ import "./index.less";
8
+
9
+ /** 弹窗标题枚举 */
10
+ const titleMap = ["人员选择", "角色选择"];
11
+
12
+ export const Selector = (props) => {
13
+ const selectorCtx = useContext(SelectContext);
14
+ const { open, type, value, onSave, treeModel, listModel, roleListModel } = selectorCtx.selectHandler;
15
+ const [groupOptions, setGroupOptions] = useState([
16
+ {
17
+ title: "Group-111",
18
+ key: "g-111",
19
+ },
20
+ {
21
+ title: "Group-222",
22
+ key: "g-222",
23
+ },
24
+ {
25
+ title: "Group-333",
26
+ key: "g-333",
27
+ },
28
+ ]);
29
+ const [options, setOptions] = useState([
30
+
31
+ ]);
32
+
33
+ const [roleOptions, setRoleOptions] = useState([
34
+ {
35
+ title: "Role-111",
36
+ key: "r-111",
37
+ },
38
+ {
39
+ title: "Role-222",
40
+ key: "r-222",
41
+ },
42
+ {
43
+ title: "Role-333",
44
+ key: "r-333",
45
+ },
46
+ ]);
47
+ const [selected, setSelected] = useState(Array.isArray(value) ? value?.map((it) => it.id || it.key) : []);
48
+ const selectedRef = useRef(
49
+ Array.isArray(value)
50
+ ? value?.map((it) => ({
51
+ ...it,
52
+ title: it.name,
53
+ key: it.id,
54
+ }))
55
+ : [],
56
+ );
57
+
58
+
59
+ const handleGetTree = () => {
60
+ treeModel?.get()
61
+ .then((res) => {
62
+ setGroupOptions(res);
63
+ })
64
+ };
65
+
66
+ const handleGetList = (data?: any) => {
67
+ (type == 2 ? roleListModel :listModel)?.get(data || {})
68
+ .then((res) => {
69
+ setOptions(roleOptions);
70
+ })
71
+ };
72
+
73
+ useEffect(() => {
74
+ if (type == 2) {
75
+ handleGetList();
76
+ } else if (type == 1) {
77
+ handleGetTree();
78
+ }
79
+ }, [type]);
80
+
81
+ useEffect(() => {
82
+
83
+ setSelected(Array.isArray(value) ? value?.map((it) => it.id || it.key) : []);
84
+ selectedRef.current = Array.isArray(value)
85
+ ? value?.map((it) => ({
86
+ ...it,
87
+ title: it.name,
88
+ key: it.id,
89
+ }))
90
+ : [];
91
+ }, [value]);
92
+
93
+ const pageRef = useRef(1);
94
+ const keywordRef = useRef("");
95
+ const keyIdRef = useRef(undefined);
96
+ const groupTreeRef = useRef();
97
+
98
+ function onModalSave() {
99
+ onSave && onSave(selectedRef.current || []);
100
+ onModalClose();
101
+ }
102
+
103
+ function onModalClose() {
104
+ setSelected([]);
105
+ selectedRef.current = [];
106
+ selectorCtx.onClose();
107
+ }
108
+
109
+ function onSearch(value, event) {
110
+ // keywordRef.current = value;
111
+ handleGetList({orgId:keyIdRef.current, name:value});
112
+
113
+ }
114
+
115
+ function groupClick(value, node) {
116
+ handleGetList({orgId:value});
117
+ keyIdRef.current = value;
118
+
119
+ // keywordRef.current = "";
120
+ // pageRef.current = 1;
121
+ // getUserOptions(value);
122
+ }
123
+
124
+ function getUserOptions(id) {
125
+ // TODO: 请求并设置用户列表
126
+ setTimeout(() => {
127
+ const list = [];
128
+ for (let i = 0; i < 10; i++) {
129
+ list.push({
130
+ title: "User-" + id + "-" + list.length,
131
+ key: "u-" + id + "-" + list.length,
132
+ });
133
+ }
134
+ console.log(list);
135
+
136
+ // pageRef.current
137
+ setOptions(list);
138
+ }, 100);
139
+ }
140
+
141
+ function onUserCheck(key) {
142
+
143
+ const is = selected.includes(key);
144
+ if (!is) {
145
+ setSelected([...selected, key])
146
+ const item = options.find((it) => it.key === key);
147
+ selectedRef.current = [...selectedRef.current, {
148
+ ...item,
149
+ id: item.key,
150
+ name: item.title,
151
+ }]
152
+ } else {
153
+ setSelected(selected.filter((it) => it !== key));
154
+ selectedRef.current = selectedRef.current.filter((it) => it.key !== key);
155
+ }
156
+ }
157
+
158
+ function deleteSelected(key) {
159
+ setSelected(selected.filter((it) => it !== key));
160
+ selectedRef.current = selectedRef.current.filter((it) => it.key !== key);
161
+ }
162
+
163
+
164
+ return (
165
+ <div className="selector">
166
+ <Modal
167
+ wrapClassName="selector-modal"
168
+ open={open}
169
+ title={titleMap[type - 1]}
170
+ width={type == 1 ? 680 : 560}
171
+ destroyOnClose
172
+ getContainer="body"
173
+ onCancel={onModalClose}
174
+ footer={
175
+ <div className="selector-modal-footer">
176
+ <Button type="primary" onClick={onModalSave}>
177
+ 保存
178
+ </Button>
179
+ <Button onClick={onModalClose}>取消</Button>
180
+ </div>
181
+ }
182
+ >
183
+ <div className="sc-user-select">
184
+ <div className="sc-user-select__left">
185
+ <div className="sc-user-select__search">
186
+ <Input.Search onSearch={onSearch} enterButton placeholder="搜索成员" />
187
+ </div>
188
+ <div className="sc-user-select__select">
189
+ {type == 1 ? <div className="sc-user-select__tree" v-loading="showGrouploading">
190
+ <Tree className="menu" ref={groupTreeRef} treeData={groupOptions} onSelect={groupClick} />
191
+ </div> : null}
192
+ <div className="sc-user-select__user" v-loading="showUserloading">
193
+ <div className="sc-user-select__user__list">
194
+ {options?.map((item) => {
195
+ return (
196
+ <div className="sc-user-select__user__item" key={item.key}>
197
+ <Checkbox
198
+ checked={selected.includes(item.key)}
199
+ onChange={(e) => onUserCheck(item.key)}
200
+ >
201
+ {item.title}
202
+ </Checkbox>
203
+ </div>
204
+ )
205
+ })}
206
+ </div>
207
+ <footer>
208
+ <Pagination simple size="small" total={50} showSizeChanger showQuickJumper></Pagination>
209
+ </footer>
210
+ </div>
211
+ </div>
212
+ </div>
213
+ <div className="sc-user-select__toicon">
214
+ <RightOutlined />
215
+ </div>
216
+ <div className="sc-user-select__selected">
217
+ <header>已选 ({selected?.length ?? 0})</header>
218
+ <ul className="sc-user-select__selected-list">
219
+ {selectedRef.current?.map((item, idx) => {
220
+ return (
221
+ <li key={item.id ?? item.key}>
222
+ <span className="name">
223
+ <Avatar size="small">{item.title?.substring(0, 1)}</Avatar>
224
+ <label>{item.title}</label>
225
+ </span>
226
+ <span className="delete">
227
+ <DeleteOutlined onClick={() => deleteSelected(item.id ?? item.key)}></DeleteOutlined>
228
+ </span>
229
+ </li>
230
+ );
231
+ })}
232
+ </ul>
233
+ </div>
234
+ </div>
235
+ </Modal>
236
+ </div>
237
+ );
238
+ };
239
+
240
+ export default Selector;
package/src/index.less ADDED
@@ -0,0 +1,466 @@
1
+ .flowlong-designer {
2
+ --el-bg-color: #ffffff; /* 默认白色背景 */
3
+ width: 100%;
4
+ .designer-affix {
5
+ position: fixed;
6
+ top: 20px;
7
+ left: 20px;
8
+ z-index: 9;
9
+ padding: 12px;
10
+ border: 1px solid #999;
11
+
12
+ .action-btn + .action-btn {
13
+ margin-left: 12px;
14
+ }
15
+ }
16
+
17
+ .json-viewer {
18
+ overflow: auto;
19
+ word-break: break-all;
20
+ white-space: pre-wrap;
21
+ }
22
+ }
23
+ .flowlong-designer .box-scale {
24
+ display: inline-block;
25
+ position: relative;
26
+ width: 100%;
27
+ align-items: flex-start;
28
+ justify-content: center;
29
+ flex-wrap: wrap;
30
+ min-width: min-content;
31
+ }
32
+
33
+ .flowlong-designer {
34
+ .node-wrap {
35
+ display: inline-flex;
36
+ width: 100%;
37
+ flex-flow: column wrap;
38
+ justify-content: flex-start;
39
+ align-items: center;
40
+ padding: 0px 0px;
41
+ position: relative;
42
+ z-index: 1;
43
+ }
44
+ .node-wrap-box {
45
+ display: inline-flex;
46
+ flex-direction: column;
47
+ position: relative;
48
+ width: 220px;
49
+ min-height: 72px;
50
+ flex-shrink: 0;
51
+ background: rgb(255, 255, 255);
52
+ border-radius: 4px;
53
+ cursor: pointer;
54
+ box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1);
55
+ }
56
+ .node-wrap-box::before {
57
+ content: "";
58
+ position: absolute;
59
+ top: -12px;
60
+ left: 50%;
61
+ transform: translateX(-50%);
62
+ width: 0px;
63
+ border-style: solid;
64
+ border-width: 8px 6px 4px;
65
+ border-color: rgb(202, 202, 202) transparent transparent;
66
+ }
67
+ .node-wrap-box.start-node:before {
68
+ content: none;
69
+ }
70
+ .node-wrap-box .title {
71
+ height: 24px;
72
+ line-height: 24px;
73
+ color: #fff;
74
+ padding-left: 16px;
75
+ padding-right: 30px;
76
+ border-radius: 4px 4px 0 0;
77
+ position: relative;
78
+ display: flex;
79
+ align-items: center;
80
+ }
81
+ .node-wrap-box .title .icon {
82
+ margin-right: 5px;
83
+ }
84
+ .node-wrap-box .title .close {
85
+ font-size: 15px;
86
+ position: absolute;
87
+ top: 50%;
88
+ transform: translateY(-50%);
89
+ right: 10px;
90
+ display: none;
91
+ }
92
+ .node-wrap-box .content {
93
+ position: relative;
94
+ padding: 15px;
95
+ }
96
+ .node-wrap-box .content .placeholder {
97
+ color: #999;
98
+ }
99
+ .node-wrap-box:hover .close {
100
+ display: block;
101
+ }
102
+ .add-node-btn-box {
103
+ width: 240px;
104
+ display: inline-flex;
105
+ flex-shrink: 0;
106
+ position: relative;
107
+ z-index: 1;
108
+ }
109
+ .add-node-btn-box:before {
110
+ content: "";
111
+ position: absolute;
112
+ top: 0px;
113
+ left: 0px;
114
+ right: 0px;
115
+ bottom: 0px;
116
+ z-index: -1;
117
+ margin: auto;
118
+ width: 2px;
119
+ height: 100%;
120
+ background-color: rgb(202, 202, 202);
121
+ }
122
+ .add-node-btn {
123
+ user-select: none;
124
+ // width: 240px;
125
+ // padding: 20px 0px 32px;
126
+ display: flex;
127
+ justify-content: center;
128
+ align-items: center;
129
+ flex-shrink: 0;
130
+ // flex-grow: 1;
131
+ }
132
+ .add-node-btn span {
133
+ }
134
+ .add-branch {
135
+ justify-content: center;
136
+ padding: 0px 10px;
137
+ position: absolute;
138
+ top: -16px;
139
+ left: 50%;
140
+ transform: translateX(-50%);
141
+ transform-origin: center center;
142
+ z-index: 1;
143
+ display: inline-flex;
144
+ align-items: center;
145
+ }
146
+ // branch-start
147
+ .branch-wrap {
148
+ display: inline-flex;
149
+ width: 100%;
150
+ }
151
+ .branch-box-wrap {
152
+ display: flex;
153
+ flex-flow: column wrap;
154
+ align-items: center;
155
+ min-height: 270px;
156
+ width: 100%;
157
+ flex-shrink: 0;
158
+ }
159
+ .col-box {
160
+ display: inline-flex;
161
+ flex-direction: column;
162
+ align-items: center;
163
+ position: relative;
164
+ }
165
+ .branch-box {
166
+ display: flex;
167
+ overflow: visible;
168
+ min-height: 180px;
169
+ height: auto;
170
+ border-bottom: 2px solid #ccc;
171
+ border-top: 2px solid #ccc;
172
+ position: relative;
173
+ margin-top: 15px;
174
+ }
175
+ .branch-box .col-box::before {
176
+ content: "";
177
+ position: absolute;
178
+ top: 0px;
179
+ left: 0px;
180
+ right: 0px;
181
+ bottom: 0px;
182
+ z-index: 0;
183
+ margin: auto;
184
+ width: 2px;
185
+ height: 100%;
186
+ background-color: rgb(202, 202, 202);
187
+ }
188
+ .condition-node {
189
+ display: inline-flex;
190
+ flex-direction: column;
191
+ min-height: 220px;
192
+ }
193
+ .condition-node-box {
194
+ padding-top: 30px;
195
+ padding-right: 50px;
196
+ padding-left: 50px;
197
+ justify-content: center;
198
+ align-items: center;
199
+ flex-grow: 1;
200
+ position: relative;
201
+ display: inline-flex;
202
+ flex-direction: column;
203
+ }
204
+ .condition-node-box::before {
205
+ content: "";
206
+ position: absolute;
207
+ top: 0px;
208
+ left: 0px;
209
+ right: 0px;
210
+ bottom: 0px;
211
+ margin: auto;
212
+ width: 2px;
213
+ height: 100%;
214
+ background-color: rgb(202, 202, 202);
215
+ }
216
+ .auto-judge {
217
+ position: relative;
218
+ width: 220px;
219
+ min-height: 72px;
220
+ background: rgb(255, 255, 255);
221
+ border-radius: 4px;
222
+ padding: 15px 15px;
223
+ cursor: pointer;
224
+ box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1);
225
+ }
226
+ .auto-judge::before {
227
+ content: "";
228
+ position: absolute;
229
+ top: -12px;
230
+ left: 50%;
231
+ transform: translateX(-50%);
232
+ width: 0px;
233
+ border-style: solid;
234
+ border-width: 8px 6px 4px;
235
+ border-color: rgb(202, 202, 202) transparent transparent;
236
+ // background: rgb(239, 239, 239);
237
+ background: #fff;
238
+ }
239
+ .auto-judge .title {
240
+ line-height: 16px;
241
+ }
242
+ .auto-judge .title .node-title {
243
+ color: #15bc83;
244
+ }
245
+ .auto-judge .title .close {
246
+ font-size: 15px;
247
+ position: absolute;
248
+ top: 15px;
249
+ right: 15px;
250
+ color: #999;
251
+ display: none;
252
+ }
253
+ .auto-judge .title .priority-title {
254
+ position: absolute;
255
+ top: 15px;
256
+ right: 15px;
257
+ color: #999;
258
+ }
259
+ .auto-judge .content {
260
+ position: relative;
261
+ padding-top: 15px;
262
+ }
263
+ .auto-judge .content .placeholder {
264
+ color: #999;
265
+ }
266
+ .auto-judge:hover {
267
+ .close {
268
+ display: block;
269
+ }
270
+ .priority-title {
271
+ display: none;
272
+ }
273
+ }
274
+ .top-left-cover-line,
275
+ .top-right-cover-line {
276
+ position: absolute;
277
+ height: 3px;
278
+ width: 50%;
279
+ background-color: #fff;
280
+ top: -2px;
281
+ }
282
+ .bottom-left-cover-line,
283
+ .bottom-right-cover-line {
284
+ position: absolute;
285
+ height: 3px;
286
+ width: 50%;
287
+ background-color: #fff;
288
+ bottom: -2px;
289
+ }
290
+ .top-left-cover-line {
291
+ left: -1px;
292
+ }
293
+ .top-right-cover-line {
294
+ right: -1px;
295
+ }
296
+ .bottom-left-cover-line {
297
+ left: -1px;
298
+ }
299
+ .bottom-right-cover-line {
300
+ right: -1px;
301
+ }
302
+ .auto-judge:hover {
303
+ .sort-left {
304
+ display: flex;
305
+ }
306
+ .sort-right {
307
+ display: flex;
308
+ }
309
+ }
310
+ .auto-judge .sort-left {
311
+ position: absolute;
312
+ top: 0;
313
+ bottom: 0;
314
+ z-index: 1;
315
+ left: 0;
316
+ display: none;
317
+ justify-content: center;
318
+ align-items: center;
319
+ flex-direction: column;
320
+ }
321
+ .auto-judge .sort-right {
322
+ position: absolute;
323
+ top: 0;
324
+ bottom: 0;
325
+ z-index: 1;
326
+ right: 0;
327
+ display: none;
328
+ justify-content: center;
329
+ align-items: center;
330
+ flex-direction: column;
331
+ }
332
+ .auto-judge .sort-left:hover,
333
+ .auto-judge .sort-right:hover {
334
+ background: #eee;
335
+ }
336
+ .auto-judge:after {
337
+ pointer-events: none;
338
+ content: "";
339
+ position: absolute;
340
+ top: 0;
341
+ bottom: 0;
342
+ left: 0;
343
+ right: 0;
344
+ z-index: 2;
345
+ border-radius: 4px;
346
+ transition: all 0.1s;
347
+ }
348
+ .auto-judge:hover:after {
349
+ border: 1px solid #3296fa;
350
+ box-shadow: 0 0 6px 0 rgba(50, 150, 250, 0.3);
351
+ }
352
+ // branch-end
353
+ .end-node {
354
+ border-radius: 50%;
355
+ font-size: 14px;
356
+ color: rgba(25, 31, 37, 0.4);
357
+ text-align: left;
358
+ }
359
+ .end-node-circle {
360
+ width: 10px;
361
+ height: 10px;
362
+ margin: auto;
363
+ border-radius: 50%;
364
+ background: #ccc;
365
+ }
366
+ .end-node-text {
367
+ margin-top: 5px;
368
+ text-align: center;
369
+ }
370
+ .node-wrap-box:after {
371
+ pointer-events: none;
372
+ content: "";
373
+ position: absolute;
374
+ top: 0;
375
+ bottom: 0;
376
+ left: 0;
377
+ right: 0;
378
+ z-index: 2;
379
+ border-radius: 4px;
380
+ transition: all 0.1s;
381
+ }
382
+ .node-wrap-box:hover:after {
383
+ border: 1px solid #3296fa;
384
+ box-shadow: 0 0 6px 0 rgba(50, 150, 250, 0.3);
385
+ }
386
+ }
387
+
388
+ .tags-list {
389
+ margin-top: 15px;
390
+ width: 100%;
391
+ }
392
+ .add-node-popover-body li {
393
+ display: inline-block;
394
+ width: 80px;
395
+ text-align: center;
396
+ padding: 10px 0;
397
+ }
398
+ .add-node-popover-body li i {
399
+ border: 1px solid var(--el-border-color-light);
400
+ width: 40px;
401
+ height: 40px;
402
+ border-radius: 50%;
403
+ text-align: center;
404
+ line-height: 38px;
405
+ font-size: 18px;
406
+ cursor: pointer;
407
+ }
408
+ .add-node-popover-body li i:hover {
409
+ border: 1px solid #3296fa;
410
+ background: #3296fa;
411
+ color: #fff !important;
412
+ }
413
+ .add-node-popover-body li p {
414
+ font-size: 12px;
415
+ margin-top: 5px;
416
+ }
417
+ .node-wrap-drawer__title {
418
+ padding-right: 40px;
419
+ }
420
+ .node-wrap-drawer__title label {
421
+ cursor: pointer;
422
+ }
423
+ .node-wrap-drawer__title label:hover {
424
+ border-bottom: 1px dashed #409eff;
425
+ }
426
+ .node-wrap-drawer__title .node-wrap-drawer__title-edit {
427
+ color: #409eff;
428
+ margin-left: 10px;
429
+ vertical-align: middle;
430
+ }
431
+
432
+ .dark .flowlong-designer {
433
+ .node-wrap-box,
434
+ .auto-judge {
435
+ background: #2b2b2b;
436
+ }
437
+ .col-box {
438
+ background: var(--el-bg-color);
439
+ }
440
+ .top-left-cover-line,
441
+ .top-right-cover-line,
442
+ .bottom-left-cover-line,
443
+ .bottom-right-cover-line {
444
+ background-color: var(--el-bg-color);
445
+ }
446
+ .node-wrap-box::before,
447
+ .auto-judge::before {
448
+ background-color: var(--el-bg-color);
449
+ }
450
+ .branch-box .add-branch {
451
+ background: var(--el-bg-color);
452
+ }
453
+ .end-node .end-node-text {
454
+ color: #ccc;
455
+ }
456
+ .auto-judge .sort-left:hover,
457
+ .auto-judge .sort-right:hover {
458
+ background: var(--el-bg-color);
459
+ }
460
+ }
461
+
462
+ .ant-drawer-footer {
463
+ .ant-btn + .ant-btn {
464
+ margin-left: 12px;
465
+ }
466
+ }