@tddc/assign-modal 3.0.9 → 3.1.0

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,932 @@
1
+ import { Checkbox, Input, Ellipsis, Segmented, Empty, Icon, TntdVirtualTree as Tree } from 'tntd';
2
+ import { useEffect, useState, useCallback, useRef, useMemo } from 'react';
3
+
4
+ import { cloneDeep, debounce } from 'lodash';
5
+ import './index.less';
6
+ import { findSameCodePath, preorder, mergeAndDeduplicate, useWindowHeight } from './utils';
7
+ import { getText } from '../../locale';
8
+
9
+ let path = []; // 上级机构到当前机构的路径
10
+
11
+ const AssignModal = (props) => {
12
+ const {
13
+ onChange,
14
+ orgList = [],
15
+ dataItem = {},
16
+ disabled,
17
+ appList,
18
+ orgTitle,
19
+ appTitle,
20
+ userTitle,
21
+ orgCheckboxTitle,
22
+ appCheckboxTitle,
23
+ userCheckboxTitle,
24
+ userList = [],
25
+ showUser,
26
+ customOrgDisabled,
27
+ customAppDisabled,
28
+ locale,
29
+ } = props;
30
+
31
+ // 封装 getText,自动传入 locale
32
+ const t = (key, ...params) => getText(key, props?.lang, locale, ...params);
33
+
34
+ let { appCodes = [], orgCodes = [], orgCode, appCode, accounts = [], account } = dataItem;
35
+
36
+ const orgMapRef = useRef({});
37
+ const appMapRef = useRef({});
38
+ const userMapRef = useRef({});
39
+
40
+ const rootNode = orgList[0];
41
+
42
+ const [allOrg, allApp, allUser] = useMemo(() => {
43
+ let org = preorder(
44
+ rootNode,
45
+ (key, node) => {
46
+ orgMapRef.current[key] = node;
47
+ },
48
+ true,
49
+ );
50
+ let app = appList.map((item) => {
51
+ appMapRef.current[item.value] = item;
52
+ return item.value;
53
+ });
54
+ let user =
55
+ userList?.map((item) => {
56
+ userMapRef.current[item.account] = item;
57
+ return item.account;
58
+ }) || [];
59
+
60
+ return [org, app, user];
61
+ }, [rootNode, appList, userList]);
62
+
63
+ const titleOptions = [
64
+ `${orgTitle || t('availableOrgs')}`,
65
+ `${appTitle || t('availableApps')}`,
66
+ `${userTitle || t('availableUsers')}`,
67
+ ];
68
+
69
+ if (!showUser) {
70
+ titleOptions.pop();
71
+ }
72
+
73
+ const [treeData, setTreeData] = useState(orgList[0]);
74
+
75
+ const [curIndex, setCurIndex] = useState(0);
76
+ const [curValue, setCurValue] = useState(titleOptions[0]);
77
+
78
+ const [checkedKeys, setCheckedKeys] = useState([]);
79
+ const [appKeys, setAppKeys] = useState(appCodes || []);
80
+ const [userKeys, setUserKeys] = useState(accounts || []);
81
+
82
+ const [allOrgChecked, setAllOrgChecked] = useState(false);
83
+ const [allAppChecked, setAllAppChecked] = useState(false);
84
+ const [allUserChecked, setAllUserChecked] = useState(false);
85
+
86
+ const [filterOrg, setFilterOrg] = useState();
87
+ const [filterUser, setFilterUser] = useState();
88
+ const [filterApp, setFilterApp] = useState();
89
+
90
+ let gap = 335;
91
+ const windowHeight = useWindowHeight(gap);
92
+
93
+ useEffect(() => {
94
+ if (dataItem && Object.keys(dataItem)?.length) {
95
+ // path 和 allOrgList 赋值
96
+ path = findSameCodePath(rootNode, orgCode);
97
+
98
+ let initOrgs = [];
99
+ let initApps = [];
100
+ let initAccounts = [];
101
+ if (orgCodes.includes('all')) {
102
+ setAllOrgChecked(orgCodes.includes('all'));
103
+ initOrgs = allOrg;
104
+ } else {
105
+ initOrgs = Array.from(new Set([...(orgCodes || []), ...path]));
106
+ }
107
+ if (appCodes.includes('all')) {
108
+ setAllAppChecked(appCodes.includes('all'));
109
+ initApps = allApp;
110
+ } else {
111
+ initApps = Array.from(new Set([...(appCodes || []), appCode]));
112
+ }
113
+
114
+ if (showUser) {
115
+ if (accounts.includes('all')) {
116
+ setAllUserChecked(true);
117
+ initAccounts = allUser;
118
+ } else {
119
+ initAccounts = Array.from(new Set([...(accounts || []), account]));
120
+ }
121
+ }
122
+
123
+ setCheckedKeys(initOrgs);
124
+ setAppKeys(initApps || []);
125
+ setUserKeys(initAccounts || []);
126
+ onChange &&
127
+ onChange({
128
+ appKeys: appCodes.includes('all') ? ['all'] : initApps,
129
+ checkedKeys: orgCodes.includes('all') ? ['all'] : initOrgs,
130
+ userKeys: accounts.includes('all') ? ['all'] : initAccounts,
131
+ appCheckAll: appCodes.includes('all'),
132
+ orgCheckAll: orgCodes.includes('all'),
133
+ userCheckAll: accounts.includes('all'),
134
+ checkData: {
135
+ apps: initApps,
136
+ orgs: initOrgs,
137
+ accounts: initAccounts,
138
+ },
139
+ });
140
+ }
141
+ }, [dataItem]);
142
+
143
+ useEffect(() => {
144
+ if (orgList) {
145
+ const loopTreeNodes = (nodes, level = 0) => {
146
+ return nodes?.map((item) => {
147
+ let orgDisabled = path.includes(item.code);
148
+
149
+ if (item.children && item.children.length > 0) {
150
+ return {
151
+ ...item,
152
+ key: item.code,
153
+ title: item.name,
154
+ value: item.code,
155
+ disabled:
156
+ orgDisabled ||
157
+ disabled ||
158
+ allOrgChecked ||
159
+ (customOrgDisabled && customOrgDisabled(item)),
160
+ children: loopTreeNodes(item.children, level + 1),
161
+ };
162
+ }
163
+ return {
164
+ ...item,
165
+ key: item.code,
166
+ value: item.code,
167
+ title: item.name,
168
+ disabled:
169
+ orgDisabled ||
170
+ disabled ||
171
+ allOrgChecked ||
172
+ (customOrgDisabled && customOrgDisabled(item)),
173
+ };
174
+ });
175
+ };
176
+
177
+ setTreeData(loopTreeNodes(orgList, 0));
178
+ }
179
+ }, [orgList, allOrgChecked, allAppChecked, allUserChecked]);
180
+
181
+ const onCheck = (...rest) => {
182
+ const [checked, node, isChecked] = rest;
183
+ const isLeaf = !node?.childrenValues?.length;
184
+ const curNode = orgMapRef.current[node.value] || {};
185
+ let { path } = curNode;
186
+
187
+ let newChecked = cloneDeep(checked);
188
+
189
+ if (!isLeaf && !isChecked) {
190
+ let arr = preorder(node);
191
+ arr.splice(0, 1);
192
+ arr.map((item) => {
193
+ let i = newChecked.findIndex((i) => i === item);
194
+ if (i !== -1) newChecked.splice(i, 1);
195
+ });
196
+ }
197
+ if (isChecked) {
198
+ newChecked.pop();
199
+ newChecked = mergeAndDeduplicate(newChecked, path);
200
+ }
201
+
202
+ setCheckedKeys(newChecked);
203
+
204
+ onChange({
205
+ appKeys: allAppChecked ? ['all'] : appKeys,
206
+ checkedKeys: newChecked,
207
+ appCheckAll: allAppChecked,
208
+ orgCheckAll: allOrgChecked,
209
+ userKeys: allUserChecked ? ['all'] : userKeys,
210
+ userCheckAll: allUserChecked,
211
+ checkData: {
212
+ apps: appKeys,
213
+ orgs: newChecked,
214
+ accounts: userKeys,
215
+ },
216
+ });
217
+ };
218
+
219
+ const assignApp = (e) => {
220
+ let value = '';
221
+ let newAppKeys = [];
222
+ if (e.target.checked) {
223
+ value = e.target.value;
224
+ newAppKeys = [...appKeys, value];
225
+ } else {
226
+ value = e.target.value;
227
+ newAppKeys = cloneDeep(appKeys);
228
+ newAppKeys.map((item, index) => {
229
+ if (value === item) {
230
+ newAppKeys.splice(index, 1);
231
+ }
232
+ });
233
+ }
234
+ setAppKeys(newAppKeys);
235
+ onChange({
236
+ appKeys: newAppKeys,
237
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
238
+ appCheckAll: allAppChecked,
239
+ orgCheckAll: allOrgChecked,
240
+ userKeys: allUserChecked ? ['all'] : userKeys,
241
+ userCheckAll: allUserChecked,
242
+ checkData: {
243
+ apps: newAppKeys,
244
+ orgs: checkedKeys,
245
+ accounts: userKeys,
246
+ },
247
+ });
248
+ };
249
+
250
+ const assignUser = (e) => {
251
+ let value = '';
252
+ let newUserKeys = [];
253
+ if (e.target.checked) {
254
+ value = e.target.value;
255
+ newUserKeys = [...userKeys, value];
256
+ } else {
257
+ value = e.target.value;
258
+ newUserKeys = cloneDeep(userKeys);
259
+ newUserKeys.map((item, index) => {
260
+ if (value === item) {
261
+ newUserKeys.splice(index, 1);
262
+ }
263
+ });
264
+ }
265
+ setUserKeys(newUserKeys);
266
+ onChange({
267
+ appKeys,
268
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
269
+ appCheckAll: allAppChecked,
270
+ orgCheckAll: allOrgChecked,
271
+ userKeys: newUserKeys,
272
+ userCheckAll: allUserChecked,
273
+ checkData: {
274
+ apps: appKeys,
275
+ orgs: checkedKeys,
276
+ accounts: newUserKeys,
277
+ },
278
+ });
279
+ };
280
+
281
+ // org全局授权
282
+ const checkAllOrg = (e) => {
283
+ let orgChecks = [];
284
+ if (e.target.checked) {
285
+ setAllOrgChecked(true);
286
+ orgChecks = preorder(rootNode);
287
+ setCheckedKeys(orgChecks);
288
+ onChange({
289
+ appKeys: allAppChecked ? ['all'] : appKeys,
290
+ checkedKeys: ['all'],
291
+ appCheckAll: allAppChecked,
292
+ orgCheckAll: true,
293
+
294
+ userKeys: allUserChecked ? ['all'] : userKeys,
295
+ userCheckAll: allUserChecked,
296
+
297
+ checkData: {
298
+ apps: appKeys,
299
+ orgs: checkedKeys,
300
+ accounts,
301
+ },
302
+ });
303
+ } else {
304
+ setAllOrgChecked(false);
305
+ let arr = orgCodes.includes('all') ? allOrg : orgCodes;
306
+ orgChecks = Array.from(new Set([...(arr || []), ...path]));
307
+
308
+ setCheckedKeys(orgChecks);
309
+ onChange({
310
+ appKeys: allAppChecked ? ['all'] : appKeys,
311
+ checkedKeys: orgChecks,
312
+ appCheckAll: allAppChecked,
313
+ orgCheckAll: false,
314
+ userKeys: allUserChecked ? ['all'] : userKeys,
315
+ userCheckAll: allUserChecked,
316
+ checkData: {
317
+ apps: appKeys,
318
+ orgs: orgChecks,
319
+ accounts,
320
+ },
321
+ });
322
+ }
323
+ };
324
+
325
+ // app全局授权
326
+ const checkedAllApp = (e) => {
327
+ let appChecks = [];
328
+ if (e.target.checked) {
329
+ setAllAppChecked(true);
330
+ appChecks = appList.map((item) => item.value);
331
+ setAppKeys(appChecks);
332
+ onChange({
333
+ appKeys: ['all'],
334
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
335
+ appCheckAll: true,
336
+ orgCheckAll: allOrgChecked,
337
+ userKeys: allUserChecked ? ['all'] : userKeys,
338
+ userCheckAll: allUserChecked,
339
+ checkData: {
340
+ apps: appChecks,
341
+ orgs: checkedKeys,
342
+ accounts,
343
+ },
344
+ });
345
+ } else {
346
+ setAllAppChecked(false);
347
+ let arr = appCodes.includes('all') ? allApp : appCodes;
348
+ appChecks = Array.from(new Set([...(arr || []), appCode]));
349
+
350
+ setAppKeys(appChecks);
351
+ onChange({
352
+ appKeys: appChecks,
353
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
354
+ appCheckAll: false,
355
+ orgCheckAll: allOrgChecked,
356
+ userKeys: allUserChecked ? ['all'] : userKeys,
357
+ userCheckAll: allUserChecked,
358
+ checkData: {
359
+ apps: appChecks,
360
+ orgs: checkedKeys,
361
+ accounts,
362
+ },
363
+ });
364
+ }
365
+ };
366
+
367
+ // account全局授权
368
+ const checkedAllUser = (e) => {
369
+ let userChecks = [];
370
+ if (e.target.checked) {
371
+ setAllUserChecked(true);
372
+ userChecks = userList.map((item) => item.account);
373
+ setUserKeys(userChecks);
374
+
375
+ onChange({
376
+ appKeys: allAppChecked ? ['all'] : appKeys,
377
+ appCheckAll: allAppChecked,
378
+
379
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
380
+ orgCheckAll: allOrgChecked,
381
+
382
+ userKeys: ['all'],
383
+ userCheckAll: true,
384
+ checkData: {
385
+ apps: appKeys,
386
+ orgs: checkedKeys,
387
+ accounts: userChecks,
388
+ },
389
+ });
390
+ } else {
391
+ setAllUserChecked(false);
392
+ const arr = accounts.includes('all') ? allUser : accounts;
393
+ userChecks = Array.from(new Set([...(arr || []), account]));
394
+
395
+ setUserKeys(userChecks);
396
+ onChange({
397
+ appKeys: allAppChecked ? ['all'] : appKeys,
398
+ appCheckAll: allAppChecked,
399
+
400
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
401
+ orgCheckAll: allOrgChecked,
402
+
403
+ userKeys: userChecks,
404
+ userCheckAll: false,
405
+
406
+ checkData: {
407
+ apps: appKeys,
408
+ orgs: checkedKeys,
409
+ accounts: userChecks,
410
+ },
411
+ });
412
+ }
413
+ };
414
+
415
+ const debouncedOrgSearch = useCallback(
416
+ debounce((nextValue) => {
417
+ setFilterOrg(nextValue);
418
+ }, 200),
419
+ [],
420
+ );
421
+ const debouncedUserSearch = useCallback(
422
+ debounce((nextValue) => {
423
+ setFilterUser(nextValue);
424
+ }, 200),
425
+ [],
426
+ );
427
+ const debouncedAppSearch = useCallback(
428
+ debounce((nextValue) => {
429
+ setFilterApp(nextValue);
430
+ }, 200),
431
+ [],
432
+ );
433
+
434
+ // 拼接机构路径显示名
435
+ const getOrgPathDisplayName = (path = []) => {
436
+ let displayName = '';
437
+ if (path.length > 0) {
438
+ displayName = path.map((item) => orgMapRef.current[item].name).join(' / ');
439
+ }
440
+
441
+ return displayName;
442
+ };
443
+
444
+ // 移除单个机构
445
+ const onRemoveSingleOrg = (node) => {
446
+ let del_arr = preorder(node);
447
+ let checked = checkedKeys.filter((item) => !del_arr.includes(item));
448
+ setCheckedKeys(checked);
449
+ setAllOrgChecked(false);
450
+
451
+ onChange({
452
+ appKeys: allAppChecked ? ['all'] : appKeys,
453
+ checkedKeys: checked,
454
+ appCheckAll: allAppChecked,
455
+ orgCheckAll: false,
456
+ userKeys: allUserChecked ? ['all'] : userKeys,
457
+ userCheckAll: allUserChecked,
458
+ checkData: {
459
+ apps: appKeys,
460
+ orgs: checked,
461
+ accounts: userKeys,
462
+ },
463
+ });
464
+ };
465
+
466
+ // 移除全部机构
467
+ const onRemoveAllOrg = () => {
468
+ let checked = [rootNode.key];
469
+ setCheckedKeys(checked);
470
+ setAllOrgChecked(false);
471
+ onChange({
472
+ appKeys: allAppChecked ? ['all'] : appKeys,
473
+ checkedKeys: checked,
474
+ appCheckAll: allAppChecked,
475
+ orgCheckAll: false,
476
+ userKeys: allUserChecked ? ['all'] : userKeys,
477
+ userCheckAll: allUserChecked,
478
+ checkData: {
479
+ apps: appKeys,
480
+ orgs: checked,
481
+ accounts: userKeys,
482
+ },
483
+ });
484
+ };
485
+
486
+ // 移除单个应用
487
+ const onRemoveSingleApp = (value) => {
488
+ let newAppKeys = cloneDeep(appKeys);
489
+ newAppKeys.map((item, index) => {
490
+ if (value === item) {
491
+ newAppKeys.splice(index, 1);
492
+ }
493
+ });
494
+ setAppKeys(newAppKeys);
495
+ setAllAppChecked(false);
496
+ onChange({
497
+ appKeys: newAppKeys,
498
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
499
+ appCheckAll: false,
500
+ orgCheckAll: allOrgChecked,
501
+ userKeys: allUserChecked ? ['all'] : userKeys,
502
+ userCheckAll: allUserChecked,
503
+ checkData: {
504
+ apps: newAppKeys,
505
+ orgs: checkedKeys,
506
+ accounts: userKeys,
507
+ },
508
+ });
509
+ };
510
+ // 移除全部应用
511
+ const onRemoveAllApp = () => {
512
+ let newAppKeys = [appCode];
513
+ setAppKeys(newAppKeys);
514
+ setAllAppChecked(false);
515
+ onChange({
516
+ appKeys: newAppKeys,
517
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
518
+ appCheckAll: false,
519
+ orgCheckAll: allOrgChecked,
520
+ userKeys: allUserChecked ? ['all'] : userKeys,
521
+ userCheckAll: allUserChecked,
522
+ checkData: {
523
+ apps: newAppKeys,
524
+ orgs: checkedKeys,
525
+ accounts: userKeys,
526
+ },
527
+ });
528
+ };
529
+
530
+ // 移除全部用户
531
+ let onRemoveAllUser = () => {
532
+ let newUserKeys = [account];
533
+ setUserKeys(newUserKeys);
534
+ setAllUserChecked(false);
535
+ onChange({
536
+ appKeys: allAppChecked ? ['all'] : appKeys,
537
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
538
+ userKeys: newUserKeys,
539
+ appCheckAll: allAppChecked,
540
+ orgCheckAll: allOrgChecked,
541
+ userCheckAll: false,
542
+ checkData: {
543
+ apps: appKeys,
544
+ orgs: checkedKeys,
545
+ accounts: newUserKeys,
546
+ },
547
+ });
548
+ };
549
+
550
+ // 移除单个用户
551
+ let onRemoveSingleUser = (value) => {
552
+ let newUserKeys = cloneDeep(userKeys);
553
+ newUserKeys.map((item, index) => {
554
+ if (value === item) {
555
+ newUserKeys.splice(index, 1);
556
+ }
557
+ });
558
+ setUserKeys(newUserKeys);
559
+ setAllUserChecked(false);
560
+ onChange({
561
+ appKeys: allAppChecked ? ['all'] : appKeys,
562
+ checkedKeys: allOrgChecked ? ['all'] : checkedKeys,
563
+ userKeys: newUserKeys,
564
+ appCheckAll: allAppChecked,
565
+ orgCheckAll: allOrgChecked,
566
+ userCheckAll: false,
567
+ checkData: {
568
+ apps: appKeys,
569
+ orgs: checkedKeys,
570
+ accounts: newUserKeys,
571
+ },
572
+ });
573
+ };
574
+
575
+ // 已选择的机构列表
576
+ let areadySelectOrg = useMemo(() => {
577
+ return checkedKeys.filter((i) => allOrg.includes(i)) || [];
578
+ }, [checkedKeys, allOrg]);
579
+ // 已选择的渠道列表
580
+ let areadySelectApp = useMemo(() => {
581
+ return appKeys.filter((i) => allApp.includes(i)) || [];
582
+ }, [appKeys, allApp]);
583
+ // 已选择的用户列表
584
+ let areadySelectUser = useMemo(() => {
585
+ return userKeys.filter((i) => allUser.includes(i)) || [];
586
+ }, [userKeys, allUser]);
587
+
588
+ // 渲染App列表
589
+ let appListDomRender = useMemo(() => {
590
+ return appList
591
+ .filter((i) => {
592
+ const { label, value } = i;
593
+ if (filterApp) {
594
+ return (
595
+ label?.toLocaleLowerCase().includes(filterApp?.toLocaleLowerCase()) ||
596
+ value?.toLocaleLowerCase().includes(filterApp?.toLocaleLowerCase())
597
+ );
598
+ }
599
+
600
+ return i;
601
+ })
602
+ .map((item, index) => {
603
+ const isCheck = appKeys?.includes(item.value);
604
+ const isOwnAppCode = appCode === item.value;
605
+ return (
606
+ <Checkbox
607
+ checked={isCheck}
608
+ disabled={
609
+ disabled ||
610
+ isOwnAppCode ||
611
+ allAppChecked ||
612
+ (customAppDisabled && customAppDisabled(item))
613
+ }
614
+ onChange={assignApp}
615
+ value={item.value}
616
+ key={index}
617
+ >
618
+ <span style={{ display: 'inline-block' }}>
619
+ <Ellipsis title={item.label} />
620
+ </span>
621
+ </Checkbox>
622
+ );
623
+ });
624
+ }, [appList, appKeys, filterApp]);
625
+
626
+ // 渲染User列表
627
+ let userListDomRender = useMemo(() => {
628
+ return (
629
+ userList
630
+ ?.filter((item) => {
631
+ if (filterUser) {
632
+ return (
633
+ item?.account?.toLocaleLowerCase().includes(filterUser?.toLocaleLowerCase()) ||
634
+ item?.userName?.toLocaleLowerCase().includes(filterUser?.toLocaleLowerCase())
635
+ );
636
+ }
637
+ return item;
638
+ })
639
+ .map((item, index) => {
640
+ const isCheck = userKeys?.includes(item.account);
641
+ const isOwnAccount = account === item.account;
642
+ return (
643
+ <Checkbox
644
+ key={item + index}
645
+ checked={isCheck}
646
+ disabled={disabled || isOwnAccount || allUserChecked}
647
+ onChange={assignUser}
648
+ value={item.account}
649
+ >
650
+ <span style={{ display: 'inline-block' }}>
651
+ <Ellipsis widthLimit={240} title={item.userName} />
652
+ </span>
653
+ </Checkbox>
654
+ );
655
+ }) || <Empty />
656
+ );
657
+ }, [userList, userKeys, filterUser]);
658
+
659
+ const renderOrgItem = (item, lang) => {
660
+ const mapResult = {
661
+ 1: {
662
+ cn: '职能部门',
663
+ en: 'Func. Dept.',
664
+ icon: 'crowd',
665
+ },
666
+ 2: {
667
+ icon: 'corporation',
668
+ },
669
+ };
670
+
671
+ const result = mapResult[item?.orgAttribute] || {};
672
+
673
+ return (
674
+ <div className="org-item-wrapper" style={{ width: 'calc(100% - 32px)' }}>
675
+ <Ellipsis
676
+ title={item.title}
677
+ widthLimit={String(item.orgAttribute) === '1' ? 'calc(100% - 90px}' : '100%'}
678
+ />
679
+ {String(item.orgAttribute) === '1' && (
680
+ <span className="org-functional-departemt-marker">{result[lang] || '职能部门'}</span>
681
+ )}
682
+ </div>
683
+ );
684
+ };
685
+
686
+ const defaultRenderItem = (item, isOrg = true) => {
687
+ if (isOrg) {
688
+ return renderOrgItem(item, props?.lang);
689
+ }
690
+ return <Ellipsis title={item.title} widthLimit={'100%'} />;
691
+ };
692
+
693
+ const canNotRemoveOrg = useMemo(() => {
694
+ return checkedKeys?.length === 1 && orgMapRef.current?.[checkedKeys[0]]?.key === rootNode?.key;
695
+ }, [checkedKeys]);
696
+
697
+ const canNotRemoveApp = useMemo(() => {
698
+ return appKeys?.length === 1 && appMapRef.current?.[appKeys[0]]?.name === appCode;
699
+ }, [appKeys]);
700
+
701
+ console.log(canNotRemoveOrg, 'canNotRemove');
702
+
703
+ // 计算面板数量和平移距离
704
+ const panelCount = showUser ? 3 : 2;
705
+ const translateX = curIndex === 0 ? 0 : `${-(100 / panelCount) * curIndex}%`;
706
+
707
+ return (
708
+ <>
709
+ <Segmented
710
+ className="menu-title"
711
+ value={curValue}
712
+ options={titleOptions}
713
+ onChange={(index) => {
714
+ setCurValue(index);
715
+ setCurIndex(titleOptions.findIndex((i) => i === index));
716
+ }}
717
+ />
718
+ <div className="assign-box-container">
719
+ <div
720
+ className="slider"
721
+ style={{
722
+ width: showUser ? '300%' : '200%',
723
+ transform: `translateX(${translateX})`,
724
+ transition: 'transform 0.2s ease',
725
+ }}
726
+ >
727
+ <div className="org-panel panel">
728
+ <div className="menu-header">
729
+ {/* 授权可用机构列表 */}
730
+ <span className="title">{orgTitle || t('authorizesOrgList')}</span>
731
+ <div className="menu-all-checked">
732
+ <Checkbox onChange={checkAllOrg} checked={allOrgChecked} disabled={disabled}>
733
+ {/* 全部机构可用 */}
734
+ {orgCheckboxTitle || t('allOrgAvailable')}
735
+ </Checkbox>
736
+ </div>
737
+ </div>
738
+ <div className="panel-menu-body">
739
+ <div className="panel-left" style={{ width: '60%' }}>
740
+ <Input
741
+ size="small"
742
+ placeholder={t('search')}
743
+ onChange={(e) => {
744
+ debouncedOrgSearch(e.target.value);
745
+ }}
746
+ suffix={<Icon type="zoom" />}
747
+ style={{ marginBottom: 16, width: 'calc(100% - 16px)' }}
748
+ />
749
+ <Tree
750
+ style={{ overflowX: 'auto' }}
751
+ isOrg={true}
752
+ treeData={treeData}
753
+ filterKey={filterOrg}
754
+ blockNode
755
+ checkable
756
+ checkStrictly={true}
757
+ checkedKeys={checkedKeys}
758
+ defaultExpandAll
759
+ onCheck={onCheck}
760
+ height={windowHeight}
761
+ titleRender={defaultRenderItem}
762
+ />
763
+ </div>
764
+ <div className="panel-right" style={{ width: '40%' }}>
765
+ <div className="select-menu-header">
766
+ <span>
767
+ {t('hasBeenSelected')}: {t('numOfOrg', areadySelectOrg.length || 0)}
768
+ </span>
769
+ <a className={canNotRemoveOrg ? 'disabeld' : ''} onClick={() => onRemoveAllOrg()}>
770
+ {t('clear')}
771
+ </a>
772
+ </div>
773
+ <ul className="select-menu-list">
774
+ {checkedKeys
775
+ .filter((i) => {
776
+ return !!orgMapRef.current[i];
777
+ })
778
+ .map((item, index) => {
779
+ let node = orgMapRef.current[item] || {};
780
+ let { path, name } = node;
781
+
782
+ let pathDisplayName = getOrgPathDisplayName(path);
783
+ let disabled = rootNode.key === item;
784
+ return (
785
+ <li key={item.value + index} className="select-menu-list-item">
786
+ <span className="org-name">
787
+ <Ellipsis title={name} />
788
+ </span>
789
+ <span className="path-name">
790
+ <Ellipsis title={pathDisplayName} />
791
+ </span>
792
+ {!disabled && (
793
+ <Icon
794
+ type="close"
795
+ className="close-icon"
796
+ onClick={() => onRemoveSingleOrg(node)}
797
+ />
798
+ )}
799
+ </li>
800
+ );
801
+ }) || <Empty />}
802
+ </ul>
803
+ </div>
804
+ </div>
805
+ </div>
806
+ <div className="app-panel panel">
807
+ <div className="menu-header">
808
+ {/* 授权可用渠道列表 */}
809
+ <span className="title">{appTitle || t('authorizesAppList')}</span>
810
+ <div className="menu-all-checked">
811
+ <Checkbox onChange={checkedAllApp} checked={allAppChecked} disabled={disabled}>
812
+ {/* 全部渠道可用 */}
813
+ {appCheckboxTitle || t('allAppAvailable')}
814
+ </Checkbox>
815
+ </div>
816
+ </div>
817
+ <div className="panel-menu-body">
818
+ <div className="panel-left">
819
+ <Input
820
+ onChange={(e) => {
821
+ debouncedAppSearch(e.target.value);
822
+ }}
823
+ placeholder={t('enterAppName')}
824
+ size="small"
825
+ suffix={<Icon type="zoom" />}
826
+ style={{ marginBottom: 16, width: 'calc(100% - 16px)' }}
827
+ />
828
+ {appListDomRender}
829
+ </div>
830
+ <div className="panel-right">
831
+ <div className="select-menu-header">
832
+ <span>
833
+ {t('hasBeenSelected')}: {t('numOfApp', areadySelectApp.length || 0)}
834
+ </span>
835
+ <a className={canNotRemoveApp ? 'disabeld' : ''} onClick={() => onRemoveAllApp()}>
836
+ {/* 清空 */}
837
+ {t('clear')}
838
+ </a>
839
+ </div>
840
+ <ul className="select-menu-list">
841
+ {appKeys.map((item, index) => {
842
+ let node = appMapRef.current[item] || {};
843
+ let { value, label } = node;
844
+
845
+ const isOwnAppCode = appCode === value;
846
+ if (!value && !label) return null; // 不显示多余数据
847
+ return (
848
+ <li key={value + index} className="select-menu-list-item">
849
+ <span className="app-name">
850
+ <Ellipsis title={label} />
851
+ </span>
852
+ {!isOwnAppCode && (
853
+ <Icon
854
+ type="close"
855
+ className="close-icon"
856
+ onClick={() => onRemoveSingleApp(value)}
857
+ />
858
+ )}
859
+ </li>
860
+ );
861
+ }) || <Empty />}
862
+ </ul>
863
+ </div>
864
+ </div>
865
+ </div>
866
+ {!!showUser && (
867
+ <div className="user-panel panel">
868
+ <div className="menu-header">
869
+ {/* 授权可用用户列表 */}
870
+ <span className="title">{userTitle || t('authorizesUserList')}</span>
871
+ <div className="menu-all-checked">
872
+ <Checkbox onChange={checkedAllUser} checked={allUserChecked} disabled={disabled}>
873
+ {/* 全部用户可用 */}
874
+ {userCheckboxTitle || t('allUserAvailable')}
875
+ </Checkbox>
876
+ </div>
877
+ </div>
878
+ <div className="panel-menu-body">
879
+ <div className="panel-left">
880
+ <Input
881
+ size="small"
882
+ placeholder={t('enterUserName')}
883
+ onChange={(e) => {
884
+ debouncedUserSearch(e.target.value);
885
+ }}
886
+ suffix={<Icon type="zoom" />}
887
+ style={{ marginBottom: 16, width: 'calc(100% - 16px)' }}
888
+ />
889
+
890
+ {userListDomRender}
891
+ </div>
892
+ <div className="panel-right">
893
+ <div className="select-menu-header">
894
+ <span>
895
+ {t('hasBeenSelected')}: {t('numOfUser', areadySelectUser.length || 0)}
896
+ </span>
897
+ <a onClick={() => onRemoveAllUser()}>{t('clear')}</a>
898
+ </div>
899
+ <ul className="select-menu-list">
900
+ {userKeys.map((item, index) => {
901
+ let node = userMapRef.current[item] || {};
902
+ let { userName } = node;
903
+
904
+ const isOwnUserCode = account === node.account;
905
+ if (!userName && !node.account) return null; // 不显示多余数据
906
+ return (
907
+ <li key={userName + index} className="select-menu-list-item">
908
+ <span className="app-name">
909
+ <Ellipsis title={userName} />
910
+ </span>
911
+ {!isOwnUserCode && (
912
+ <Icon
913
+ type="close"
914
+ className="close-icon"
915
+ onClick={() => onRemoveSingleUser(node.account)}
916
+ />
917
+ )}
918
+ </li>
919
+ );
920
+ }) || <Empty />}
921
+ </ul>
922
+ </div>
923
+ </div>
924
+ </div>
925
+ )}
926
+ </div>
927
+ </div>
928
+ </>
929
+ );
930
+ };
931
+
932
+ export default AssignModal;