@qmlight/web-platform-components 1.0.3 → 1.0.6

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.
@@ -12,4 +12,5 @@ export default {
12
12
  QFC_PUBLIC: `${prefix}/dcp-base-public`,
13
13
  QFC_AUTH: `${prefix}/dcp-base-auth`,
14
14
  GWGL_SERVICE: `/gwgl-service`,
15
+ FT_FLOAT: `${prefix}/ft-oa-service`,
15
16
  };
@@ -11,7 +11,7 @@ export const getOrgsByConditions = (params) => {
11
11
  return axios.post(`${SERVER.QFC_BASE}/lowcode/getOrgsByConditions`, params);
12
12
  };
13
13
  export const recentUserPage = (params) => {
14
- return axios.post(`${SERVER.QFC_BASE}/custom/getCommonGroup`, params);
14
+ return axios.post(`${SERVER.QFC_BASE}/lowcode/getOuterCustomGroup`, params);
15
15
  };
16
16
 
17
17
  export const getUsersByConditions = (params) => {
@@ -0,0 +1,325 @@
1
+ import React, { useEffect, useRef, useState, useImperativeHandle } from 'react';
2
+ import { message, QmSearchTree } from 'dcp-design-react';
3
+ import {
4
+ getAllCustomGroups,
5
+ createCustomGroups,
6
+ deleteCustomGroup,
7
+ getUsersByCustomGroup,
8
+ } from '../../api/tabList';
9
+ import isEmpty from 'lodash-es/isEmpty';
10
+ import { UserOutlined, FolderOutlined, EditOutlined, DeleteOutlined } from '@/icons';
11
+ import './style.less';
12
+
13
+ const MultipleTree = React.forwardRef((props: any, ref) => {
14
+ const {
15
+ mode,
16
+ onDataChange,
17
+ selectedKeys = [],
18
+ targetKeys = [],
19
+ onItemSelectAll,
20
+ onValueChange,
21
+ type = 'default',
22
+ onDoubleClickChange,
23
+ actionHandle,
24
+ } = props;
25
+ const [fetchParams, setFetchParams] = useState<any>({});
26
+ const treeData = useRef<any[]>([]);
27
+ const searchTreeRef = useRef<any>();
28
+ const [itemKeys, setItemKeys] = useState<any[]>([]);
29
+ const timer = useRef<any>(null);
30
+ useEffect(() => {
31
+ if (selectedKeys) {
32
+ const treeList = getTreeList(treeData.current, []);
33
+ const newList = treeList
34
+ .filter((item) => selectedKeys.includes(item.id))
35
+ .map((item) => item.newId);
36
+ setItemKeys(newList || []);
37
+ }
38
+
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, [selectedKeys]);
41
+ const onRefreshChange = (id?) => {
42
+ if (id) {
43
+ setFetchParams({ newId: id, refesh: true });
44
+ return;
45
+ }
46
+ setFetchParams({});
47
+ };
48
+ useImperativeHandle(ref, () => {
49
+ return {
50
+ onRefresh: onRefreshChange,
51
+ };
52
+ });
53
+ const updateTreeData = (list, key, children) =>
54
+ list.map((node) => {
55
+ if (node.id === key) {
56
+ return {
57
+ ...node,
58
+ children,
59
+ };
60
+ }
61
+ if (node.children) {
62
+ return {
63
+ ...node,
64
+ children: updateTreeData(node.children, key, children),
65
+ };
66
+ }
67
+ return node;
68
+ });
69
+ const getNodeData = (data, id, field) => {
70
+ for (let i = 0; i < data.length; i++) {
71
+ if (data[i].id === id) {
72
+ return data[i];
73
+ }
74
+ if (!isEmpty(data[i].children)) {
75
+ return getNodeData(data[i].children, id, field);
76
+ }
77
+ }
78
+ return field;
79
+ };
80
+ const getIsLeft = (a1, a2) => {
81
+ if (type === 'default' || type === 'customOrg') {
82
+ return !a1;
83
+ }
84
+ return !a2;
85
+ };
86
+ const getCheckAble = (item) => {
87
+ if (type === 'default' || type === 'org') {
88
+ return !(targetKeys.includes(item.id) || targetKeys.includes(item.parentId));
89
+ }
90
+ if (type === 'customOrg') {
91
+ return (
92
+ !item.orgtype &&
93
+ item.orgtype !== 0 &&
94
+ !(targetKeys.includes(item.id) || targetKeys.includes(item.parentId))
95
+ );
96
+ }
97
+ if (type === 'doc') {
98
+ return !(targetKeys.includes(item.id) || targetKeys.includes(item.parentId));
99
+ }
100
+ return (
101
+ item.orgtype === 2 &&
102
+ !(
103
+ targetKeys.includes(item.id) ||
104
+ targetKeys.includes(item.parentId) ||
105
+ targetKeys.includes(`${item.parentId}_${item.id}`)
106
+ )
107
+ );
108
+ };
109
+
110
+ const getData = async (params) => {
111
+ params.id = params.newId;
112
+ const treeList = getTreeList(treeData.current, []);
113
+ const field = treeList.find((item) => item.id === params['id']) || {
114
+ hasChildren: true,
115
+ };
116
+ const { newId, refesh, ...newParams } = params;
117
+ const res = await (!params?.id
118
+ ? getAllCustomGroups({})
119
+ : getUsersByCustomGroup({ ids: [params.id] }));
120
+ if (res.code === 200) {
121
+ if (!params['id']) {
122
+ // const list = getNodeData(res.data, !hasChildren);
123
+ const list = res.data.map((item) => {
124
+ return {
125
+ ...item,
126
+ checkable: getCheckAble(item),
127
+ name: item.title,
128
+ newId: item.id,
129
+ orgtype: 2,
130
+ isLeaf: false,
131
+ };
132
+ });
133
+ console.log(list);
134
+ treeData.current = list;
135
+ const treeList = getTreeList(list, []);
136
+ onDataChange &&
137
+ onDataChange(
138
+ treeList.map((item) => {
139
+ return {
140
+ ...item,
141
+ key: item.id,
142
+ title: item.name,
143
+ };
144
+ })
145
+ );
146
+
147
+ return {
148
+ ...res,
149
+ data: list,
150
+ };
151
+ } else {
152
+ const { userList } = res.data[0] || {};
153
+ const list = userList.map((item) => {
154
+ return {
155
+ ...item,
156
+ isLeaf: true,
157
+ id: item.loginName,
158
+ parentId: params.id,
159
+ newId: `${params.id}_${item.loginName}`,
160
+ name: item.userName,
161
+ checkable: getCheckAble({ ...item, id: item.loginName }),
162
+ };
163
+ });
164
+
165
+ treeData.current = updateTreeData(treeData.current, params.id, list);
166
+ const treeList = getTreeList(treeData.current, []);
167
+ onDataChange &&
168
+ onDataChange(
169
+ treeList.map((item) => {
170
+ return {
171
+ ...item,
172
+ key: item.id,
173
+ title: item.name,
174
+ };
175
+ })
176
+ );
177
+ if (refesh) {
178
+ return {
179
+ ...res,
180
+ data: treeData.current,
181
+ };
182
+ }
183
+ return {
184
+ ...res,
185
+ data: list,
186
+ };
187
+ }
188
+ }
189
+ onRefreshChange(false);
190
+ return res;
191
+ };
192
+ const getTreeList = (treeData, list) => {
193
+ treeData.forEach((item) => {
194
+ list.push(item);
195
+ if (item.children) {
196
+ getTreeList(item.children, list);
197
+ }
198
+ });
199
+ return list;
200
+ };
201
+
202
+ const onItemChange = async (node) => {
203
+ if (node.length > 0) {
204
+ onItemSelectAll(
205
+ node.map((item) => item.id),
206
+ true
207
+ );
208
+ if (selectedKeys.length) {
209
+ return;
210
+ }
211
+ } else {
212
+ onItemSelectAll(selectedKeys, false);
213
+ }
214
+ };
215
+ useEffect(() => {
216
+ if (searchTreeRef.current) {
217
+ const treeList = getTreeList(treeData.current, []);
218
+ treeList.forEach((item) => {
219
+ if (item.orgtype === 0) {
220
+ searchTreeRef.current.UPDATE_RECORD(item.id, {
221
+ checkable: false,
222
+ });
223
+ } else {
224
+ searchTreeRef.current.UPDATE_RECORD(item.newId, {
225
+ checkable: getCheckAble(item),
226
+ });
227
+ }
228
+ });
229
+ }
230
+ // eslint-disable-next-line react-hooks/exhaustive-deps
231
+ }, [targetKeys]);
232
+
233
+ return (
234
+ <div className="search-tree-page">
235
+ {/* {type !== 'doc' && <DropDownList onDataChange={onDropDataChange} />} */}
236
+
237
+ <div className="search-tree-page-content">
238
+ <QmSearchTree
239
+ ref={searchTreeRef}
240
+ filterable={false}
241
+ showCollapse={false}
242
+ asyncLoad={true}
243
+ multiple={mode === 'multiple'}
244
+ fetch={{
245
+ api: getData,
246
+ params: fetchParams,
247
+ }}
248
+ // checkStrictly={true}
249
+ value={itemKeys}
250
+ checkStrategy={'SHOW_CHILD'}
251
+ onCheckChange={(node: any) => {
252
+ clearTimeout(timer.current);
253
+ timer.current = setTimeout(async () => {
254
+ await onItemSelectAll(selectedKeys, false);
255
+ onItemChange(node);
256
+ }, 300);
257
+ }}
258
+ onSelectChange={(node: any) => {
259
+ if (!mode) {
260
+ if (
261
+ (!node?.orgtype && node.orgtype !== 0) ||
262
+ (type === 'org' && node.orgtype !== 0)
263
+ ) {
264
+ setItemKeys([node.id]);
265
+ onValueChange && onValueChange({ ...node, value: node.id, title: node.name });
266
+ }
267
+ }
268
+ }}
269
+ titleRender={(node) => {
270
+ return node.orgtype === 2 ? (
271
+ <span
272
+ className="tree-header-multip"
273
+ onDoubleClick={(e) => {
274
+ if (!node?.checkable) {
275
+ return;
276
+ }
277
+ clearTimeout(timer.current);
278
+ if (!targetKeys?.includes(node.id)) {
279
+ onDoubleClickChange(node.id);
280
+ }
281
+ }}
282
+ >
283
+ <span>
284
+ <FolderOutlined /> {node.name}
285
+ </span>
286
+ <div className="item-action">
287
+ <EditOutlined
288
+ onClick={(e) => actionHandle(e, 'edit', node)}
289
+ style={{ marginRight: 8, fontSize: 14 }}
290
+ />
291
+ <DeleteOutlined
292
+ onClick={(e) => actionHandle(e, 'del', node)}
293
+ style={{ marginRight: 8, fontSize: 14 }}
294
+ />
295
+ </div>
296
+ </span>
297
+ ) : (
298
+ <span
299
+ onDoubleClick={(e) => {
300
+ if (!node?.checkable) {
301
+ return;
302
+ }
303
+ clearTimeout(timer.current);
304
+ if (!targetKeys?.includes(node.id)) {
305
+ onDoubleClickChange(node.id);
306
+ }
307
+ }}
308
+ >
309
+ <UserOutlined /> {node.name}
310
+ </span>
311
+ );
312
+ }}
313
+ fieldsDefine={{
314
+ valueKey: 'newId',
315
+ textKey: 'name',
316
+ }}
317
+ showSearchBar={false}
318
+ // dataSource={treeData}
319
+ />
320
+ </div>
321
+ </div>
322
+ );
323
+ });
324
+ MultipleTree.displayName = 'MultipleTree';
325
+ export default MultipleTree;
@@ -93,7 +93,7 @@ const CustomModal = ({ actionInfo, onClose, setAcitonInfo, mode }) => {
93
93
  }
94
94
  const field = {
95
95
  ...data,
96
- userIds: userList.map((item) => item.key),
96
+ userIds: userList.map((item) => item.oldId || item.key),
97
97
  };
98
98
  const res = await (!data?.id
99
99
  ? createCustomGroups(field)
@@ -197,7 +197,7 @@ const CustomModal = ({ actionInfo, onClose, setAcitonInfo, mode }) => {
197
197
  <></>
198
198
  )}
199
199
 
200
- <QmButton onClick={() => onClose()}>取消</QmButton>
200
+ <QmButton onClick={() => onClose('noRefesh')}>取消</QmButton>
201
201
  </QmSpace>
202
202
 
203
203
  <SearchAssistanceModel
@@ -219,7 +219,6 @@ const CustomModal = ({ actionInfo, onClose, setAcitonInfo, mode }) => {
219
219
  {
220
220
  label: '组织结构',
221
221
  key: '4',
222
- type: 'customOrg',
223
222
  },
224
223
  ]}
225
224
  type={'customOrg'}
@@ -1,17 +1,18 @@
1
- import React, { useState, useEffect, useRef, useLayoutEffect } from "react";
2
- import { DcpButton, DcpModal, Collapse, Spin } from "dcp-design-react";
3
- import { PlusOutlined } from "@/icons";
1
+ import React, { useState, useEffect, useRef, useLayoutEffect } from 'react';
2
+ import { DcpButton, DcpModal, Collapse, Spin } from 'dcp-design-react';
3
+ import { PlusOutlined } from '@/icons';
4
4
  import {
5
5
  getAllCustomGroups,
6
6
  createCustomGroups,
7
7
  deleteCustomGroup,
8
8
  getUsersByCustomGroup,
9
- } from "../../api/tabList";
10
- import TabList from "../tabList";
11
- import "./style.less";
12
- import { Message } from "@/utils";
13
- import CustomModal from "./customModal";
14
- import { EditOutlined, DeleteOutlined } from "@/icons";
9
+ } from '../../api/tabList';
10
+ import TabList from '../tabList';
11
+ import './style.less';
12
+ import { Message } from '@/utils';
13
+ import CustomModal from './customModal';
14
+ import { EditOutlined, DeleteOutlined } from '@/icons';
15
+ import MultipleTree from './MultipleTree';
15
16
  const { Panel } = Collapse;
16
17
  const CustomOrg = (props) => {
17
18
  const {
@@ -22,21 +23,23 @@ const CustomOrg = (props) => {
22
23
  onItemSelect,
23
24
  onValueChange,
24
25
  onDataChange,
26
+ onItemSelectAll,
25
27
  } = props;
26
28
  const [dataSource, setData] = useState<any>([]);
27
29
  const [itemKeys, setItemKeys] = useState<any[]>([]);
28
30
  const [actionInfo, setAcitonInfo] = useState<any>({
29
- type: "add",
31
+ type: 'add',
30
32
  visible: false,
31
33
  });
32
34
  const [fetchParams, setFetchParams] = useState({});
35
+ const multipleTreeRef = useRef<any>();
33
36
 
34
37
  const [moveKey, setMoveKey] = useState<string | null>(null);
35
38
  const [activeKeys, setActiveKeys] = useState<string[]>([]);
36
39
  const userList = React.useRef<any[]>([]);
37
40
  const dataList = React.useRef<any>([]);
38
41
  const [loading, setLoading] = useState(false);
39
- const [loaingChild, setLoadingChild] = useState("");
42
+ const [loaingChild, setLoadingChild] = useState('');
40
43
  const getData = async (flag?) => {
41
44
  setLoading(true);
42
45
  const res = await getAllCustomGroups({}).finally(() => {
@@ -47,21 +50,21 @@ const CustomOrg = (props) => {
47
50
  return {
48
51
  ...item,
49
52
  key: item.id,
50
- orgtype: "customOrg",
53
+ orgtype: 'customOrg',
51
54
  };
52
55
  });
53
56
 
54
57
  if (mode) {
55
58
  userList.current = list;
56
- setData(list);
59
+
57
60
  dataList.current = list;
61
+ setData(list);
58
62
  onDataChange && onDataChange(list);
59
63
  return;
60
64
  }
61
65
  if (flag) {
62
66
  dataList.current = list.map((item) => {
63
- const field =
64
- dataList.current.find((items) => items.id === item.id) || {};
67
+ const field = dataList.current.find((items) => items.id === item.id) || {};
65
68
  return {
66
69
  ...item,
67
70
  ...field,
@@ -70,6 +73,8 @@ const CustomOrg = (props) => {
70
73
  setData(dataList.current);
71
74
  return;
72
75
  } else {
76
+ setData(list);
77
+ dataList.current = list;
73
78
  }
74
79
 
75
80
  const firstId = list.find((_, index) => index === 0).id;
@@ -112,7 +117,10 @@ const CustomOrg = (props) => {
112
117
  };
113
118
 
114
119
  useEffect(() => {
115
- getData();
120
+ if (mode !== 'multiple') {
121
+ getData();
122
+ }
123
+
116
124
  // onDataChange && onDataChange(dataSource);
117
125
  // eslint-disable-next-line react-hooks/exhaustive-deps
118
126
  }, []);
@@ -120,19 +128,18 @@ const CustomOrg = (props) => {
120
128
  setItemKeys(selectedKeys || []);
121
129
  }, [selectedKeys]);
122
130
  const itemSelect = (value, checked) => {
123
- if (mode === "multiple") {
131
+ if (mode === 'multiple') {
124
132
  onItemSelect && onItemSelect(value, checked);
125
133
  return;
126
134
  }
127
135
  setItemKeys([value]);
128
136
  const field = userList.current.find((item) => item.id === value);
129
- onValueChange &&
130
- onValueChange({ ...field, value: field.id, label: field.title });
137
+ onValueChange && onValueChange({ ...field, value: field.id, label: field.title });
131
138
  };
132
139
  const onItemAction = async (act, item) => {
133
- if (act === "edit") {
140
+ if (act === 'edit') {
134
141
  setAcitonInfo({
135
- type: "edit",
142
+ type: 'edit',
136
143
  data: {
137
144
  id: item.id,
138
145
  title: item.title,
@@ -142,11 +149,13 @@ const CustomOrg = (props) => {
142
149
  });
143
150
  return;
144
151
  }
145
- if (act === "del") {
152
+ if (act === 'del') {
146
153
  const res = await deleteCustomGroup({ id: item.id });
147
154
  if (res.code === 200) {
148
- Message("删除成功", "success");
149
-
155
+ Message('删除成功', 'success');
156
+ if (mode === 'multiple') {
157
+ multipleTreeRef?.current?.onRefresh();
158
+ }
150
159
  getData(true);
151
160
  }
152
161
  }
@@ -154,23 +163,23 @@ const CustomOrg = (props) => {
154
163
 
155
164
  const onClose = (id?) => {
156
165
  setAcitonInfo({
157
- type: "add",
166
+ type: 'add',
158
167
  visible: false,
159
168
  });
160
169
  if (!mode && id) {
161
170
  getUserData(id);
162
171
  return;
163
172
  }
164
- getData(true);
173
+ multipleTreeRef?.current?.onRefresh(id);
165
174
  };
166
175
  const actionHandle = (e, flag, info) => {
167
176
  e.stopPropagation();
168
- if (flag === "edit") {
169
- onItemAction("edit", info);
177
+ if (flag === 'edit') {
178
+ onItemAction('edit', info);
170
179
  return;
171
180
  }
172
- if (flag === "del") {
173
- onItemAction("del", info);
181
+ if (flag === 'del') {
182
+ onItemAction('del', info);
174
183
  }
175
184
  };
176
185
 
@@ -183,7 +192,7 @@ const CustomOrg = (props) => {
183
192
  icon={<PlusOutlined />}
184
193
  onClick={() => {
185
194
  setAcitonInfo({
186
- type: "add",
195
+ type: 'add',
187
196
  visible: true,
188
197
  });
189
198
  }}
@@ -199,9 +208,7 @@ const CustomOrg = (props) => {
199
208
  setActiveKeys(val);
200
209
  if (val.length) {
201
210
  const newId = val[val.length - 1];
202
- const userFlag = dataList.current.find(
203
- (item) => item.id === newId,
204
- )?.userList;
211
+ const userFlag = dataList.current.find((item) => item.id === newId)?.userList;
205
212
  if (!userFlag) {
206
213
  getUserData(newId);
207
214
  }
@@ -216,11 +223,11 @@ const CustomOrg = (props) => {
216
223
  extra={
217
224
  <div className="item-action">
218
225
  <EditOutlined
219
- onClick={(e) => actionHandle(e, "edit", item)}
226
+ onClick={(e) => actionHandle(e, 'edit', item)}
220
227
  style={{ marginRight: 8, fontSize: 14 }}
221
228
  />
222
229
  <DeleteOutlined
223
- onClick={(e) => actionHandle(e, "del", item)}
230
+ onClick={(e) => actionHandle(e, 'del', item)}
224
231
  style={{ marginRight: 8, fontSize: 14 }}
225
232
  />
226
233
  </div>
@@ -231,9 +238,7 @@ const CustomOrg = (props) => {
231
238
  onItemSelect={itemSelect}
232
239
  selectedKeys={itemKeys}
233
240
  // loading={item.id === loaingChild}
234
- dataSource={item.userList?.filter(
235
- (items) => !targetKeys.includes(items.id),
236
- )}
241
+ dataSource={item.userList?.filter((items) => !targetKeys.includes(items.id))}
237
242
  />
238
243
  </Panel>
239
244
  );
@@ -241,17 +246,20 @@ const CustomOrg = (props) => {
241
246
  </Collapse>
242
247
  </div>
243
248
  )}
244
- {mode === "multiple" && (
249
+ {mode === 'multiple' && (
245
250
  <div className="custom-org-page-list">
246
- <TabList
251
+ <MultipleTree
247
252
  onDoubleClickChange={onDoubleClickChange}
248
- onItemSelect={itemSelect}
249
- selectedKeys={itemKeys}
250
- type={"edit"}
251
- onItemAction={onItemAction}
252
- dataSource={dataSource.filter(
253
- (item) => !targetKeys.includes(item.id),
254
- )}
253
+ targetKeys={targetKeys}
254
+ selectedKeys={selectedKeys}
255
+ mode={'multiple'}
256
+ onItemSelect={onItemSelect}
257
+ onValueChange={onValueChange}
258
+ onDataChange={onDataChange}
259
+ onItemSelectAll={onItemSelectAll}
260
+ type="default"
261
+ ref={multipleTreeRef}
262
+ actionHandle={actionHandle}
255
263
  />
256
264
  </div>
257
265
  )}
@@ -262,15 +270,24 @@ const CustomOrg = (props) => {
262
270
  visible={actionInfo.visible}
263
271
  onClose={() =>
264
272
  setAcitonInfo({
265
- type: "add",
273
+ type: 'add',
266
274
  visible: false,
267
275
  })
268
276
  }
269
- wrapClassName={"search-assistance-modal"}
277
+ wrapClassName={'search-assistance-modal'}
270
278
  >
271
279
  <CustomModal
272
280
  actionInfo={actionInfo}
273
- onClose={onClose}
281
+ onClose={(flag) => {
282
+ if (flag === 'noRefesh') {
283
+ setAcitonInfo({
284
+ type: 'add',
285
+ visible: false,
286
+ });
287
+ return;
288
+ }
289
+ onClose(flag);
290
+ }}
274
291
  mode={mode}
275
292
  setAcitonInfo={setAcitonInfo}
276
293
  />
@@ -6,6 +6,17 @@
6
6
  height:100%;
7
7
  }
8
8
  }
9
+ .ant-tree .ant-tree-treenode{
10
+ width: 100%;
11
+ }
12
+ .ant-tree .ant-tree-node-content-wrapper{
13
+ display: inline-block;
14
+ flex: 1;
15
+ }
16
+ .tree-header-multip{
17
+ display: flex;
18
+ justify-content: space-between;
19
+ }
9
20
  .ant-collapse-content-box{
10
21
  padding: 0px;
11
22
  }