@hzab/flowlong-designer 0.0.1 → 0.0.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.
package/CHANGELOG.md CHANGED
@@ -1,2 +1,5 @@
1
+ # @hzab/flowlong-designer@0.0.2
2
+ 重构人员选择
3
+
1
4
  # @hzab/flowlong-designer@0.0.1
2
- 组件初始化
5
+ 组件初始化
package/README.md CHANGED
@@ -20,9 +20,32 @@ import Demo from "@hzab/flowlong-designer";
20
20
 
21
21
  ### InfoPanel Attributes
22
22
 
23
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
24
+ | ------ | ------ | ---- | ------ | ----------------- |
25
+ | value | Object | 否 | - | 数据信息的 schema |
26
+ | listConfig | Object | 否 | - | 人员选择的 config |
27
+ | roleListConfig | Object | 否 | - | 角色选择的 config |
28
+ | initiatorListConfig | Object | 否 | - | 发起人选择的 config |
29
+
30
+
31
+
32
+ ### InfoPanel listConfig|roleListConfig | initiatorListConfig
33
+
23
34
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
24
35
  | ------ | ------ | ---- | ------ | ----------------- |
25
- | schema | Object | | - | 数据信息的 schema |
36
+ | value | Object | | [] | 选中的人员数据 |
37
+ | model | Object | 否 | - | 列表的请求 model (getListApi) |
38
+ | searchModel | Object | 否 | - | 搜索列表的请求 model (getListApi) |
39
+ | queryKey | string | 否 | parentId | 列表的请求 model 的入参 key |
40
+ | searchQueryKey | string | 否 | search | 搜索列表的请求 model 的入参 key |
41
+ | labelKey | string | 否 | label | labelKey |
42
+ | valueKey | string | 否 | value | valueKey |
43
+ | imgKey | string | 否 | img | imgKey 头像 |
44
+ | isUserKey | string | 否 | isUser | 区分部门和人员 |
45
+ | hasPagination | boolean | 否 | true | 列表是否分页 |
46
+ | hasSearch | boolean | 否 | true | 是否有搜索 |
47
+ | hasSearchPagination | boolean | 否 | true | 搜索列表是否分页 |
48
+
26
49
 
27
50
  # 组件开发流程
28
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/flowlong-designer",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "自定义审批流配置组件",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -46,6 +46,9 @@
46
46
  ]
47
47
  },
48
48
  "dependencies": {
49
+ "@hzab/data-model": "^1.7.0",
50
+ "@hzab/deep-list": "^0.0.2",
51
+ "@hzab/group-user-selector": "^0.0.4",
49
52
  "nanoid": "^3.3.7"
50
53
  }
51
54
  }
@@ -199,7 +199,7 @@ export const Approver = (props) => {
199
199
  f.nodeAssigneeList = selected;
200
200
  return { ...f };
201
201
  });
202
- })
202
+ },2)
203
203
  }
204
204
  >
205
205
  选择人员
@@ -252,7 +252,7 @@ export const Approver = (props) => {
252
252
  f.nodeAssigneeList = selected;
253
253
  return { ...f };
254
254
  });
255
- })
255
+ },2)
256
256
  }
257
257
  >
258
258
  选择角色
@@ -0,0 +1,30 @@
1
+ import { Input, InputNumber } from "antd";
2
+ import GroupUserSelectorModal from "../GroupUserSelectorModal";
3
+
4
+ interface FormMapProps {
5
+ type: string;
6
+ onChange?: (v: any) => void;
7
+ value?: any;
8
+ }
9
+ const Field = (props: FormMapProps) => {
10
+ const { type, onChange, value } = props;
11
+
12
+ return (
13
+ <>
14
+ {["day", "hour"].includes(type) && (
15
+ <Input
16
+ value={value}
17
+ placeholder="值"
18
+ type="number"
19
+ onChange={(e) => {
20
+ onChange(e.target.value);
21
+ }}
22
+ ></Input>
23
+ )}
24
+ {["dept", "useId"].includes(type) && (
25
+ <GroupUserSelectorModal type={type} onChange={onChange} value={value}></GroupUserSelectorModal>
26
+ )}
27
+ </>
28
+ );
29
+ };
30
+ export default Field;
@@ -0,0 +1,4 @@
1
+ .groupUserSelectorModal {
2
+ max-height: 500px;
3
+ overflow-y: auto;
4
+ }
@@ -0,0 +1,97 @@
1
+ import DataModel from "@hzab/data-model";
2
+ import GroupUserSelector from "@hzab/group-user-selector";
3
+ import { Input, Modal } from "antd";
4
+ import { useMemo, useRef, useState } from "react";
5
+ import "./index.less";
6
+ const fieldMap = {
7
+ dept: "deptList",
8
+ useId: "userNameVos",
9
+ };
10
+ const titleMap = {
11
+ dept: "部门",
12
+ useId: "用户",
13
+ };
14
+ const GroupUserSelectorModal = (props) => {
15
+ const { type, onChange, value = [] } = props;
16
+ const [open, setOpen] = useState(false);
17
+ const groupUserSelectorRef = useRef(null);
18
+ const deptModel = new DataModel({
19
+ getListApi: "/api/v1/sysOrg/getDeptList",
20
+ });
21
+ const userModel = new DataModel({
22
+ getListApi: "/api/v1/userinfo/userDetailListV2",
23
+ query: {
24
+ conditionStatus: 0,
25
+ },
26
+ getListMap(data) {
27
+ return {
28
+ ...data,
29
+ name: data.userName,
30
+ id: data.userId,
31
+ isUser: true,
32
+ };
33
+ },
34
+ });
35
+ const model = useMemo(() => {
36
+ if (type === "dept") {
37
+ return deptModel;
38
+ }
39
+ if (type === "useId") {
40
+ return userModel;
41
+ }
42
+ }, [type]);
43
+ const onOk = () => {
44
+ onChange(groupUserSelectorRef.current?.selectedList);
45
+ setOpen(false);
46
+ };
47
+
48
+ const inputValue = useMemo(() => {
49
+ if (type === "dept" && value) {
50
+ return value?.map((item) => item?.label)?.join(",");
51
+ }
52
+ if (type === "useId" && value) {
53
+ return value?.map((item) => item?.name)?.join(",");
54
+ }
55
+ }, [value, type]);
56
+ const userListConfig = {
57
+ searchQueryKey: "userName",
58
+ labelKey: "name",
59
+ valueKey: "id",
60
+ };
61
+ return (
62
+ <div>
63
+ <Input
64
+ value={inputValue}
65
+ readOnly
66
+ onClick={() => {
67
+ setOpen(true);
68
+ }}
69
+ placeholder="请点击编辑"
70
+ style={{ cursor: "pointer" }}
71
+ ></Input>
72
+ <Modal
73
+ title={titleMap[type]}
74
+ open={open}
75
+ onCancel={() => {
76
+ setOpen(false);
77
+ }}
78
+ width={800}
79
+ okText={"确认"}
80
+ cancelText={"取消"}
81
+ onOk={onOk}
82
+ centered
83
+ destroyOnClose
84
+ >
85
+ <div className="groupUserSelectorModal">
86
+ <GroupUserSelector
87
+ value={value || []}
88
+ ref={groupUserSelectorRef}
89
+ model={model}
90
+ {...(type === "useId" ? userListConfig : {})}
91
+ ></GroupUserSelector>
92
+ </div>
93
+ </Modal>
94
+ </div>
95
+ );
96
+ };
97
+ export default GroupUserSelectorModal;
@@ -2,10 +2,12 @@
2
2
  .branch-box .add-branch {
3
3
  background: var(--el-bg-color);
4
4
  }
5
+
5
6
  .branch-wrap {
6
7
  display: inline-flex;
7
8
  width: 100%;
8
9
  }
10
+
9
11
  .branch-box-wrap {
10
12
  display: flex;
11
13
  flex-flow: column wrap;
@@ -14,12 +16,14 @@
14
16
  width: 100%;
15
17
  flex-shrink: 0;
16
18
  }
19
+
17
20
  .col-box {
18
21
  display: inline-flex;
19
22
  flex-direction: column;
20
23
  align-items: center;
21
24
  position: relative;
22
25
  }
26
+
23
27
  .branch-box {
24
28
  display: flex;
25
29
  overflow: visible;
@@ -30,6 +34,7 @@
30
34
  position: relative;
31
35
  margin-top: 15px;
32
36
  }
37
+
33
38
  .branch-box .col-box::before {
34
39
  content: "";
35
40
  position: absolute;
@@ -43,11 +48,13 @@
43
48
  height: 100%;
44
49
  background-color: rgb(202, 202, 202);
45
50
  }
51
+
46
52
  .condition-node {
47
53
  display: inline-flex;
48
54
  flex-direction: column;
49
55
  min-height: 220px;
50
56
  }
57
+
51
58
  .condition-node-box {
52
59
  padding-top: 30px;
53
60
  padding-right: 50px;
@@ -59,6 +66,7 @@
59
66
  display: inline-flex;
60
67
  flex-direction: column;
61
68
  }
69
+
62
70
  .condition-node-box::before {
63
71
  content: "";
64
72
  position: absolute;
@@ -71,6 +79,7 @@
71
79
  height: 100%;
72
80
  background-color: rgb(202, 202, 202);
73
81
  }
82
+
74
83
  .auto-judge {
75
84
  position: relative;
76
85
  width: 220px;
@@ -81,6 +90,7 @@
81
90
  cursor: pointer;
82
91
  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.1);
83
92
  }
93
+
84
94
  .auto-judge::before {
85
95
  content: "";
86
96
  position: absolute;
@@ -93,12 +103,15 @@
93
103
  border-color: rgb(202, 202, 202) transparent transparent;
94
104
  background: rgb(239, 239, 239);
95
105
  }
106
+
96
107
  .auto-judge .title {
97
108
  line-height: 16px;
98
109
  }
110
+
99
111
  .auto-judge .title .node-title {
100
112
  color: #15bc83;
101
113
  }
114
+
102
115
  .auto-judge .title .delete-btn {
103
116
  font-size: 15px;
104
117
  position: absolute;
@@ -107,35 +120,43 @@
107
120
  color: #999;
108
121
  display: none;
109
122
  }
123
+
110
124
  .auto-judge .title .priority-title {
111
125
  position: absolute;
112
126
  top: 15px;
113
127
  right: 15px;
114
128
  color: #999;
115
129
  }
130
+
116
131
  .auto-judge .content {
117
132
  position: relative;
118
133
  padding-top: 15px;
119
134
  }
135
+
120
136
  .auto-judge .content .placeholder {
121
137
  color: #999;
122
138
  }
139
+
123
140
  .auto-judge:hover {
124
141
  .delete-btn {
125
142
  display: block;
126
143
  }
144
+
127
145
  .priority-title {
128
146
  display: none;
129
147
  }
130
148
  }
149
+
131
150
  .auto-judge:hover {
132
151
  .sort-left {
133
152
  display: flex;
134
153
  }
154
+
135
155
  .sort-right {
136
156
  display: flex;
137
157
  }
138
158
  }
159
+
139
160
  .auto-judge .sort-left {
140
161
  position: absolute;
141
162
  top: 0;
@@ -147,6 +168,7 @@
147
168
  align-items: center;
148
169
  flex-direction: column;
149
170
  }
171
+
150
172
  .auto-judge .sort-right {
151
173
  position: absolute;
152
174
  top: 0;
@@ -158,10 +180,12 @@
158
180
  align-items: center;
159
181
  flex-direction: column;
160
182
  }
183
+
161
184
  .auto-judge .sort-left:hover,
162
185
  .auto-judge .sort-right:hover {
163
186
  background: #eee;
164
187
  }
188
+
165
189
  .auto-judge:after {
166
190
  pointer-events: none;
167
191
  content: "";
@@ -174,10 +198,12 @@
174
198
  border-radius: 4px;
175
199
  transition: all 0.1s;
176
200
  }
201
+
177
202
  .auto-judge:hover:after {
178
203
  border: 1px solid #3296fa;
179
204
  box-shadow: 0 0 6px 0 rgba(50, 150, 250, 0.3);
180
205
  }
206
+
181
207
  .top-left-cover-line,
182
208
  .top-right-cover-line {
183
209
  position: absolute;
@@ -186,6 +212,7 @@
186
212
  background-color: #fff;
187
213
  top: -2px;
188
214
  }
215
+
189
216
  .bottom-left-cover-line,
190
217
  .bottom-right-cover-line {
191
218
  position: absolute;
@@ -194,15 +221,19 @@
194
221
  background-color: #fff;
195
222
  bottom: -2px;
196
223
  }
224
+
197
225
  .top-left-cover-line {
198
226
  left: -1px;
199
227
  }
228
+
200
229
  .top-right-cover-line {
201
230
  right: -1px;
202
231
  }
232
+
203
233
  .bottom-left-cover-line {
204
234
  left: -1px;
205
235
  }
236
+
206
237
  .bottom-right-cover-line {
207
238
  right: -1px;
208
239
  }
@@ -271,7 +302,12 @@
271
302
  }
272
303
 
273
304
  div:not(:first-child) {
274
- margin-left: 16px;
305
+ // margin-left: 16px;
306
+ }
307
+
308
+ .condition-content-box-item {
309
+ margin-right: 16px;
310
+
275
311
  }
276
312
  }
277
313
 
@@ -311,9 +347,10 @@
311
347
  padding: 12px;
312
348
  }
313
349
  }
350
+
314
351
  .ant-drawer-footer {
315
- .ant-btn + .ant-btn {
352
+ .ant-btn+.ant-btn {
316
353
  margin-left: 12px;
317
354
  }
318
355
  }
319
- }
356
+ }
@@ -5,6 +5,7 @@ import { LeftOutlined, DeleteOutlined, RightOutlined, EditOutlined } from "@ant-
5
5
  import AddNode from "../AddNode";
6
6
 
7
7
  import "./index.less";
8
+ import Field from "./components/Field";
8
9
 
9
10
  /**
10
11
  * 操作符选项列表
@@ -19,6 +20,13 @@ export const operatorOptions = [
19
20
  { label: "包含", value: "include" },
20
21
  { label: "不包含", value: "notinclude" },
21
22
  ];
23
+ /**条件字段下拉数据 */
24
+ const conditionOption = [
25
+ { label: "天", value: "day" },
26
+ { label: "小时", value: "hour" },
27
+ { label: "部门", value: "dept" },
28
+ { label: "用户id", value: "useId" },
29
+ ];
22
30
 
23
31
  export const Branch = (props) => {
24
32
  const { modelValue: nodeConfig, onChange, ItemSlot } = props;
@@ -89,7 +97,17 @@ export const Branch = (props) => {
89
97
  var { conditionList } = nodeConfig.conditionNodes[idx];
90
98
  if (conditionList && conditionList.length == 1) {
91
99
  const text = conditionList
92
- .map((conditionGroup) => conditionGroup.map((item) => `${item.label}${item.operator}${item.value}`))
100
+ .map((conditionGroup) =>
101
+ conditionGroup.map((item) => {
102
+ if (item?.field === "dept") {
103
+ return `${item.label}${item.operator}${item.value?.map((el) => el?.label)}`;
104
+ }
105
+ if (item?.field === "useId") {
106
+ return `${item.label}${item.operator}${item.value?.map((el) => el?.userName)}`;
107
+ }
108
+ return `${item.label}${item.operator}${item.value}`;
109
+ }),
110
+ )
93
111
  .join(" 和 ");
94
112
  return text;
95
113
  } else if (conditionList && conditionList.length > 1) {
@@ -142,7 +160,7 @@ export const Branch = (props) => {
142
160
  function onConditionAdd(conditionList) {
143
161
  conditionList.push({
144
162
  label: "",
145
- field: "",
163
+ field: "day",
146
164
  operator: "=",
147
165
  value: "",
148
166
  });
@@ -264,7 +282,7 @@ export const Branch = (props) => {
264
282
  onClose={onDrawerClose}
265
283
  destroyOnClose
266
284
  getContainer="body"
267
- width={600}
285
+ width={800}
268
286
  title={
269
287
  <div className="node-wrap-drawer-title">
270
288
  {isEditTitle ? (
@@ -336,33 +354,40 @@ export const Branch = (props) => {
336
354
  setForm((f) => ({ ...f }));
337
355
  }}
338
356
  placeholder="描述"
357
+ className="condition-content-box-item"
339
358
  />
340
- <Input
359
+ <Select
360
+ options={conditionOption}
341
361
  value={condition.field}
342
362
  onChange={(e) => {
343
- condition.field = e.target.value;
363
+ condition.field = e;
364
+ condition.value = null;
344
365
  // 更新数据
345
366
  setForm((f) => ({ ...f }));
346
367
  }}
368
+ className="condition-content-box-item"
347
369
  placeholder="条件字段"
348
370
  />
349
371
  <Select
350
372
  value={condition.operator}
351
373
  onChange={(val) => {
352
374
  condition.operator = val;
375
+ // 更新数据
376
+ setForm((f) => ({ ...f }));
353
377
  }}
354
378
  placeholder="请选择"
355
379
  options={operatorOptions}
380
+ className="condition-content-box-item"
356
381
  ></Select>
357
- <Input
382
+ <Field
358
383
  value={condition.value}
384
+ type={condition.field}
359
385
  onChange={(e) => {
360
- condition.value = e.target.value;
386
+ condition.value = e;
361
387
  // 更新数据
362
388
  setForm((f) => ({ ...f }));
363
389
  }}
364
- placeholder="值"
365
- />
390
+ ></Field>
366
391
  </div>
367
392
  </div>
368
393
  </div>
@@ -143,10 +143,10 @@ export const Promoter = (props) => {
143
143
  f.nodeAssigneeList = selected;
144
144
  return { ...f };
145
145
  });
146
- })
146
+ }, 1)
147
147
  }
148
148
  >
149
- 选择角色
149
+ 选择人员
150
150
  </Button>
151
151
  <div className="tags-list">
152
152
  {form.nodeAssigneeList?.map((it, idx) => {
@@ -1,9 +1,10 @@
1
1
  import { useRef, useState, useContext } from "react";
2
- import { Drawer, Button, Input, Form, Tag, Switch } from "antd";
3
- import { EditOutlined, SendOutlined, DeleteOutlined } from "@ant-design/icons";
2
+ import { Drawer, Button, Input, Form, Tag, Switch, Select, Radio, InputNumber } from "antd";
3
+ import { EditOutlined, SendOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons";
4
4
 
5
5
  import AddNode from "../AddNode";
6
6
  import { SelectContext } from "../../../Selector/SelectContext";
7
+ import { setTypeOptions, selectModeOptions, directorModeOptions, termModeOptions, examineModeOptions } from "./options";
7
8
 
8
9
  import "./index.less";
9
10
 
@@ -86,6 +87,21 @@ export const Send = (props) => {
86
87
  setForm((f) => ({ ...f }));
87
88
  }
88
89
 
90
+ function onUserDel(idx) {
91
+ setForm((f) => {
92
+ f.nodeAssigneeList.splice(idx, 1);
93
+ return { ...f };
94
+ });
95
+ }
96
+
97
+ function onRoleDel(idx) {
98
+ setForm((f) => {
99
+ f.nodeAssigneeList.splice(idx, 1);
100
+ return { ...f };
101
+ });
102
+ }
103
+
104
+
89
105
  return (
90
106
  <div className="send">
91
107
  <div className="node-wrap">
@@ -148,7 +164,161 @@ export const Send = (props) => {
148
164
  }
149
165
  >
150
166
  <Form label-position="top" initialValues={form}>
151
- <Form.Item label="选择要抄送的人员">
167
+ <Form.Item label="抄送人类型" name="setType">
168
+ <Select
169
+ options={setTypeOptions}
170
+ value={form.setType}
171
+ onSelect={(val) => {
172
+ setForm((f) => {
173
+ // 清空 人员、角色 列表数组
174
+ f.nodeAssigneeList = [];
175
+ f.setType = val;
176
+ return { ...f };
177
+ });
178
+ }}
179
+ />
180
+ </Form.Item>
181
+
182
+ {form.setType === 1 ? (
183
+ <Form.Item label="选择成员" name="nodeAssigneeList">
184
+ <Button
185
+ type="primary"
186
+ icon={<PlusOutlined />}
187
+ onClick={() =>
188
+ selectorCtx.setSelectHandler(
189
+ 1,
190
+ form.nodeAssigneeList,
191
+ (selected) => {
192
+ setForm((f) => {
193
+ // 设置 人员、角色 列表数组
194
+ f.nodeAssigneeList = selected;
195
+ return { ...f };
196
+ });
197
+ },
198
+ 2
199
+ )
200
+ }
201
+ >
202
+ 选择人员
203
+ </Button>
204
+ <div className="tags-list">
205
+ {form.nodeAssigneeList?.map((user, idx) => {
206
+ return (
207
+ <Tag
208
+ key={user.id || idx}
209
+ className="node-assignee-item"
210
+ closable
211
+ onClose={() => {
212
+ onUserDel(idx);
213
+ }}
214
+ >
215
+ {user.name}
216
+ </Tag>
217
+ );
218
+ })}
219
+ </div>
220
+ </Form.Item>
221
+ ) : null}
222
+
223
+ {form.setType === 2 ? (
224
+ <Form.Item label="指定主管" name="aaa">
225
+ 发起人的第
226
+ <InputNumber
227
+ min={1}
228
+ value={form.examineLevel}
229
+ onChange={(val) => {
230
+ setForm((f) => {
231
+ form.examineLevel = val;
232
+ return { ...f };
233
+ });
234
+ }}
235
+ />
236
+ 级主管
237
+ </Form.Item>
238
+ ) : null}
239
+
240
+ {form.setType === 3 ? (
241
+ <Form.Item label="选择角色" name="nodeAssigneeList">
242
+ <Button
243
+ type="primary"
244
+ icon={<PlusOutlined />}
245
+ onClick={() =>
246
+ selectorCtx.setSelectHandler(2, form.nodeAssigneeList, (selected) => {
247
+ setForm((f) => {
248
+ // 设置 人员、角色 列表数组
249
+ f.nodeAssigneeList = selected;
250
+ return { ...f };
251
+ });
252
+ },2)
253
+ }
254
+ >
255
+ 选择角色
256
+ </Button>
257
+ <div className="tags-list">
258
+ {form.nodeAssigneeList?.map((it, idx) => {
259
+ return (
260
+ <Tag
261
+ key={it.id || idx}
262
+ className="node-assignee-item"
263
+ closable
264
+ onClose={() => {
265
+ onRoleDel(idx);
266
+ }}
267
+ >
268
+ {it.name}
269
+ </Tag>
270
+ );
271
+ })}
272
+ </div>
273
+ </Form.Item>
274
+ ) : null}
275
+
276
+ {form.setType === 4 ? (
277
+ <Form.Item label="指定主管" name="selectMode">
278
+ <Radio.Group
279
+ options={selectModeOptions}
280
+ value={form.selectMode}
281
+ onChange={(e) => {
282
+ setForm((f) => {
283
+ form.selectMode = e.target.value;
284
+ return { ...f };
285
+ });
286
+ }}
287
+ />
288
+ </Form.Item>
289
+ ) : null}
290
+
291
+ {form.setType === 7 ? (
292
+ <Form.Item label="指定主管" name="directorMode">
293
+ <Radio.Group
294
+ options={directorModeOptions}
295
+ value={form.directorMode}
296
+ onChange={(e) => {
297
+ setForm((f) => {
298
+ form.directorMode = e.target.value;
299
+ return { ...f };
300
+ });
301
+ }}
302
+ />
303
+ </Form.Item>
304
+ ) : null}
305
+
306
+ {form.directorMode === 1 ? (
307
+ <Form.Item label="直到发起人的第" name="directorLevel">
308
+ <InputNumber
309
+ min={1}
310
+ value={form.directorLevel}
311
+ onChange={(val) => {
312
+ setForm((f) => {
313
+ form.directorLevel = val;
314
+ return { ...f };
315
+ });
316
+ }}
317
+ />{" "}
318
+ 级主管
319
+ </Form.Item>
320
+ ) : null}
321
+ {/* <Form.Item label="选择要抄送的人员">
152
322
  <Button
153
323
  type="primary"
154
324
  onClick={() => {
@@ -190,7 +360,7 @@ export const Send = (props) => {
190
360
  });
191
361
  }}
192
362
  ></Switch>
193
- </Form.Item>
363
+ </Form.Item> */}
194
364
  </Form>
195
365
  </Drawer>
196
366
  </div>
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 审批人员类型
3
+ */
4
+ export const setTypeOptions = [
5
+ { label: "指定成员", value: 1 },
6
+ { label: "主管", value: 2 },
7
+ { label: "角色", value: 3 },
8
+ { label: "发起人自选", value: 4 },
9
+ { label: "发起人自己", value: 5 },
10
+ { label: "连续多级主管", value: 7 },
11
+ ];
12
+
13
+ /**
14
+ * 发起人自选
15
+ */
16
+ export const selectModeOptions = [
17
+ { label: "自选一个人", value: 1 },
18
+ { label: "自选多个人", value: 2 },
19
+ ];
20
+
21
+ /**
22
+ * 连续主管审批终点
23
+ */
24
+ export const directorModeOptions = [
25
+ { label: "直到最上层主管", value: 0 },
26
+ { label: "自定义审批终点", value: 1 },
27
+ ];
28
+
29
+ /**
30
+ * 审批期限超时后执行
31
+ */
32
+ export const termModeOptions = [
33
+ { label: "自动通过", value: 0 },
34
+ { label: "自动拒绝", value: 1 },
35
+ ];
36
+
37
+ /**
38
+ * 多人审批时审批方式
39
+ */
40
+ export const examineModeOptions = [
41
+ { label: "按顺序依次审批", value: 1 },
42
+ { label: "会签 (可同时审批,每个人必须审批通过)", value: 2 },
43
+ { label: "或签 (有一人审批通过即可)", value: 3 },
44
+ ];
@@ -5,13 +5,16 @@ export interface ISelectHandlerI {
5
5
  open: boolean;
6
6
  /** 选择类型 */
7
7
  type: number;
8
+ /** 抽屉选择类型 */
9
+ drawerType: number;
10
+
8
11
  /** 已选中的数据 */
9
12
  value: [];
10
13
  /** 选中保存回调 */
11
14
  onSave: (selected) => void;
12
- listModel,
13
- treeModel,
14
- roleListModel,
15
+ roleListConfig,
16
+ listConfig,
17
+ initiatorListConfig,
15
18
  }
16
19
 
17
20
  /**
@@ -21,12 +24,13 @@ export const SelectContext = createContext({
21
24
  selectHandler: {
22
25
  open: false,
23
26
  type: undefined,
27
+ drawerType: undefined,
24
28
  value: [],
25
- onSave: (s) => {},
26
- listModel:undefined,
27
- treeModel:undefined,
28
- roleListModel:undefined
29
+ onSave: (s) => { },
30
+ roleListConfig: {},
31
+ listConfig: {},
32
+ initiatorListConfig: {},
29
33
  },
30
- setSelectHandler(type, value, onSave) {},
31
- onClose() {},
34
+ setSelectHandler(type, value, onSave, drawerType) { },
35
+ onClose() { },
32
36
  });
@@ -1,7 +1,7 @@
1
1
  import { useRef, useState, useContext, useEffect } from "react";
2
2
  import { Modal, Input, Button, Tree, Checkbox, Pagination, Avatar } from "antd";
3
3
  import { RightOutlined, DeleteOutlined } from "@ant-design/icons";
4
-
4
+ import GroupUserSelector from '@hzab/group-user-selector'
5
5
  import { SelectContext } from "./SelectContext";
6
6
 
7
7
  import "./index.less";
@@ -11,154 +11,157 @@ const titleMap = ["人员选择", "角色选择"];
11
11
 
12
12
  export const Selector = (props) => {
13
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("");
14
+ const { open, type, value, onSave, roleListConfig, listConfig, initiatorListConfig, drawerType } = 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
95
  const keyIdRef = useRef(undefined);
96
96
  const groupTreeRef = useRef();
97
+ const selectorRef = useRef(undefined);
97
98
 
98
99
  function onModalSave() {
99
- onSave && onSave(selectedRef.current || []);
100
+ console.log(selectorRef.current?.selectedList);
101
+
102
+ onSave && onSave(selectorRef.current?.selectedList || []);
100
103
  onModalClose();
101
104
  }
102
105
 
103
106
  function onModalClose() {
104
- setSelected([]);
105
- selectedRef.current = [];
107
+ // setSelected([]);
108
+ // selectedRef.current = [];
106
109
  selectorCtx.onClose();
107
110
  }
108
111
 
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
- }
112
+ // function onSearch(value, event) {
113
+ // // keywordRef.current = value;
114
+ // handleGetList({orgId:keyIdRef.current, name:value});
115
+
116
+ // }
117
+
118
+ // function groupClick(value, node) {
119
+ // handleGetList({orgId:value});
120
+ // keyIdRef.current = value;
121
+
122
+ // // keywordRef.current = "";
123
+ // // pageRef.current = 1;
124
+ // // getUserOptions(value);
125
+ // }
126
+
127
+ // function getUserOptions(id) {
128
+ // // TODO: 请求并设置用户列表
129
+ // setTimeout(() => {
130
+ // const list = [];
131
+ // for (let i = 0; i < 10; i++) {
132
+ // list.push({
133
+ // title: "User-" + id + "-" + list.length,
134
+ // key: "u-" + id + "-" + list.length,
135
+ // });
136
+ // }
137
+ // console.log(list);
138
+
139
+ // // pageRef.current
140
+ // setOptions(list);
141
+ // }, 100);
142
+ // }
143
+
144
+ // function onUserCheck(key) {
145
+
146
+ // const is = selected.includes(key);
147
+ // if (!is) {
148
+ // setSelected([...selected, key])
149
+ // const item = options.find((it) => it.key === key);
150
+ // selectedRef.current = [...selectedRef.current, {
151
+ // ...item,
152
+ // id: item.key,
153
+ // name: item.title,
154
+ // }]
155
+ // } else {
156
+ // setSelected(selected.filter((it) => it !== key));
157
+ // selectedRef.current = selectedRef.current.filter((it) => it.key !== key);
158
+ // }
159
+ // }
160
+
161
+ // function deleteSelected(key) {
162
+ // setSelected(selected.filter((it) => it !== key));
163
+ // selectedRef.current = selectedRef.current.filter((it) => it.key !== key);
164
+ // }
162
165
 
163
166
 
164
167
  return (
@@ -167,7 +170,7 @@ export const Selector = (props) => {
167
170
  wrapClassName="selector-modal"
168
171
  open={open}
169
172
  title={titleMap[type - 1]}
170
- width={type == 1 ? 680 : 560}
173
+ width={800}
171
174
  destroyOnClose
172
175
  getContainer="body"
173
176
  onCancel={onModalClose}
@@ -180,7 +183,8 @@ export const Selector = (props) => {
180
183
  </div>
181
184
  }
182
185
  >
183
- <div className="sc-user-select">
186
+ <GroupUserSelector ref={selectorRef} {...(drawerType == 1 ? initiatorListConfig : type == 2 ? roleListConfig : listConfig)} value={value}/>
187
+ {/* <div className="sc-user-select">
184
188
  <div className="sc-user-select__left">
185
189
  <div className="sc-user-select__search">
186
190
  <Input.Search onSearch={onSearch} enterButton placeholder="搜索成员" />
@@ -231,7 +235,7 @@ export const Selector = (props) => {
231
235
  })}
232
236
  </ul>
233
237
  </div>
234
- </div>
238
+ </div> */}
235
239
  </Modal>
236
240
  </div>
237
241
  );
package/src/index.tsx CHANGED
@@ -44,25 +44,32 @@ function copy(str) {
44
44
  }
45
45
 
46
46
  function FlowlongDesigner(props) {
47
- const { value, flowName, listModel, treeModel ,roleListModel} = props;
47
+ const {
48
+ value,
49
+ flowName,
50
+ roleListConfig,
51
+ listConfig,
52
+ initiatorListConfig
53
+ } = props;
48
54
  const [drawer, setDrawer] = useState(false);
49
55
  const [zoom, setZoom] = useState(1);
50
56
  const [data, setData] = useState(Object.keys(value || {}).length > 0 ? value : getInitNodeData({ name: flowName }));
51
57
  const [selectHandler, setSelectHandler] = useState<ISelectHandlerI>({
52
58
  open: false,
53
59
  type: -1,
60
+ drawerType: -1,
54
61
  value: [],
55
- onSave: (s) => {},
56
- listModel,
57
- treeModel,
58
- roleListModel
62
+ onSave: (s) => { },
63
+ roleListConfig: {},
64
+ listConfig: {},
65
+ initiatorListConfig: {},
59
66
  });
60
67
 
61
68
  useEffect(() => {
62
69
  value && setData(value);
63
70
  }, [value]);
64
71
 
65
- function saveAsPng() {}
72
+ function saveAsPng() { }
66
73
  function copyParseJson() {
67
74
  copy(JSON.stringify(data, null, 2));
68
75
  }
@@ -79,11 +86,29 @@ function FlowlongDesigner(props) {
79
86
  <SelectContext.Provider
80
87
  value={{
81
88
  selectHandler,
82
- setSelectHandler(type, value, onSave) {
83
- setSelectHandler({ open: true, type, value, onSave , listModel, treeModel, roleListModel});
89
+ setSelectHandler(type, value, onSave, drawerType) {
90
+ setSelectHandler({
91
+ open: true,
92
+ type,
93
+ drawerType,
94
+ value,
95
+ onSave,
96
+ roleListConfig,
97
+ listConfig,
98
+ initiatorListConfig
99
+ });
84
100
  },
85
101
  onClose() {
86
- setSelectHandler({ open: false, type: -1, value: [], onSave: (s) => {} , listModel, treeModel, roleListModel});
102
+ setSelectHandler({
103
+ open: false,
104
+ type: -1,
105
+ drawerType: -1,
106
+ value: [],
107
+ onSave: (s) => { },
108
+ roleListConfig,
109
+ listConfig,
110
+ initiatorListConfig
111
+ });
87
112
  },
88
113
  }}
89
114
  >