Skip to content

Commit a956fbc

Browse files
committed
tmp org api rewrite (#4304)
* sync collection * remove lock * tmp org api rewrite
1 parent db7510c commit a956fbc

File tree

13 files changed

+65
-98
lines changed

13 files changed

+65
-98
lines changed

docSite/content/zh-cn/docs/development/upgrading/492.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ weight: 799
1818
2. 知识库分块增加自定义分隔符预设值,同时支持自定义换行符分割。
1919
3. 外部变量改名:自定义变量。 并且支持在测试时调试,在分享链接中,该变量直接隐藏。
2020
4. 集合同步时,支持同步修改标题。
21+
5. 团队成员管理重构,抽离主流 IM SSO(企微、飞书、钉钉),并支持通过自定义 SSO 接入 FastGPT。同时完善与外部系统的成员同步。
2122

2223
## ⚙️ 优化
2324

packages/global/support/user/team/org/type.d.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import type { TeamPermission } from 'support/permission/user/controller';
1+
import type { TeamPermission } from '../../../permission/user/controller';
22
import { ResourcePermissionType } from '../type';
3-
import { SourceMemberType } from 'support/user/type';
3+
import { SourceMemberType } from '../../type';
44

55
type OrgSchemaType = {
66
_id: string;
77
teamId: string;
88
pathId: string;
99
path: string;
1010
name: string;
11-
avatar?: string;
11+
avatar: string;
1212
description?: string;
1313
updateTime: Date;
1414
};
@@ -20,7 +20,12 @@ type OrgMemberSchemaType = {
2020
tmbId: string;
2121
};
2222

23-
type OrgType = Omit<OrgSchemaType, 'avatar'> & {
23+
export type OrgListItemType = OrgSchemaType & {
24+
permission: TeamPermission;
25+
total: number; // members + children orgs
26+
};
27+
28+
export type OrgType = Omit<OrgSchemaType, 'avatar'> & {
2429
avatar: string;
2530
permission: TeamPermission;
2631
members: OrgMemberSchemaType[];

packages/service/support/permission/memberGroup/memberGroupSchema.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
22
import { connectionMongo, getMongoModel } from '../../../common/mongo';
33
import { MemberGroupSchemaType } from '@fastgpt/global/support/permission/memberGroup/type';
4-
import { GroupMemberCollectionName } from './groupMemberSchema';
54
const { Schema } = connectionMongo;
65

76
export const MemberGroupCollectionName = 'team_member_groups';

projects/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "app",
3-
"version": "4.9.1",
3+
"version": "4.9.2",
44
"private": false,
55
"scripts": {
66
"dev": "next dev",

projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { useUserStore } from '@/web/support/user/useUserStore';
2424
import { useToast } from '@fastgpt/web/hooks/useToast';
2525
import { DEFAULT_TEAM_AVATAR } from '@fastgpt/global/common/system/constants';
2626
import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
27+
import { GroupMemberItemType } from '@fastgpt/global/support/permission/memberGroup/type';
28+
import { useMount } from 'ahooks';
2729

2830
export type GroupFormType = {
2931
members: {
@@ -46,26 +48,20 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
4648
return groups.find((item) => item._id === editGroupId);
4749
}, [editGroupId, groups]);
4850

49-
const { data: groupMembers } = useRequest2(
50-
() => {
51-
if (editGroupId) return getGroupMembers(editGroupId);
52-
return Promise.resolve(undefined);
53-
},
54-
{
55-
manual: false,
56-
onSuccess: (data) => {
57-
setMembers(data ?? []);
58-
}
59-
}
60-
);
61-
6251
const allMembers = useContextSelector(TeamContext, (v) => v.members);
6352
const refetchMembers = useContextSelector(TeamContext, (v) => v.refetchMembers);
6453
const MemberScrollData = useContextSelector(TeamContext, (v) => v.MemberScrollData);
6554
const [hoveredMemberId, setHoveredMemberId] = useState<string>();
6655

6756
const selectedMembersRef = useRef<HTMLDivElement>(null);
68-
const [members, setMembers] = useState(groupMembers || []);
57+
const [members, setMembers] = useState<GroupMemberItemType[]>([]);
58+
59+
useMount(async () => {
60+
if (editGroupId) {
61+
const data = await getGroupMembers(editGroupId);
62+
setMembers(data);
63+
}
64+
});
6965

7066
const [searchKey, setSearchKey] = useState('');
7167
const filtered = useMemo(() => {
@@ -80,7 +76,7 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
8076
const { runAsync: onUpdate, loading: isLoadingUpdate } = useRequest2(
8177
async () => {
8278
if (!editGroupId || !members.length) return;
83-
console.log(members);
79+
8480
return putUpdateGroup({
8581
groupId: editGroupId,
8682
memberList: members
@@ -209,7 +205,7 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
209205
<Flex borderLeft="1px" borderColor="myGray.200" flexDirection="column" p="4" h={'100%'}>
210206
<Box mt={2}>{t('common:chosen') + ': ' + members.length}</Box>
211207
<MemberScrollData ScrollContainerRef={selectedMembersRef} mt={3} flex={'1 0 0'} h={0}>
212-
{members?.map((member) => {
208+
{members.map((member) => {
213209
return (
214210
<HStack
215211
onMouseEnter={() => setHoveredMemberId(member.tmbId)}

projects/app/src/pageComponents/account/team/MemberTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
236236
<Box className={'textEllipsis'}>
237237
{member.memberName}
238238
{member.status !== 'active' && (
239-
<Tag ml="2" colorSchema="gray">
239+
<Tag ml="2" colorSchema="gray" bg={'myGray.100'} color={'myGray.700'}>
240240
{t('account_team:leave')}
241241
</Tag>
242242
)}

projects/app/src/pageComponents/account/team/OrgManage/OrgInfoModal.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
77
import MyModal from '@fastgpt/web/components/common/MyModal';
88
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
99
import { useTranslation } from 'next-i18next';
10-
import dynamic from 'next/dynamic';
1110
import { useForm } from 'react-hook-form';
1211

1312
export type OrgFormType = {

projects/app/src/pageComponents/account/team/OrgManage/OrgMemberManageModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type React from 'react';
2121
import { useEffect, useMemo, useState } from 'react';
2222
import { useContextSelector } from 'use-context-selector';
2323
import { TeamContext } from '../context';
24-
import { OrgType } from '@fastgpt/global/support/user/team/org/type';
24+
import { OrgListItemType, OrgType } from '@fastgpt/global/support/user/team/org/type';
2525
import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
2626

2727
export type GroupFormType = {
@@ -46,7 +46,7 @@ function OrgMemberManageModal({
4646
refetchOrgs,
4747
onClose
4848
}: {
49-
currentOrg: OrgType;
49+
currentOrg: OrgListItemType;
5050
refetchOrgs: () => void;
5151
onClose: () => void;
5252
}) {

projects/app/src/pageComponents/account/team/OrgManage/OrgMoveModal.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { putMoveOrg } from '@/web/support/user/team/org/api';
22
import { Button, ModalBody, ModalFooter } from '@chakra-ui/react';
3-
import type { OrgType } from '@fastgpt/global/support/user/team/org/type';
3+
import type { OrgListItemType, OrgType } from '@fastgpt/global/support/user/team/org/type';
44
import MyModal from '@fastgpt/web/components/common/MyModal';
55
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
66
import { useTranslation } from 'next-i18next';
@@ -15,13 +15,13 @@ function OrgMoveModal({
1515
onClose,
1616
onSuccess
1717
}: {
18-
movingOrg: OrgType;
19-
orgs: OrgType[];
18+
movingOrg: OrgListItemType;
19+
orgs: OrgListItemType[];
2020
onClose: () => void;
2121
onSuccess: () => void;
2222
}) {
2323
const { t } = useTranslation();
24-
const [selectedOrg, setSelectedOrg] = useState<OrgType>();
24+
const [selectedOrg, setSelectedOrg] = useState<OrgListItemType>();
2525
const { userInfo } = useUserStore();
2626
const team = userInfo?.team!;
2727

projects/app/src/pageComponents/account/team/OrgManage/index.tsx

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
Tr,
1515
VStack
1616
} from '@chakra-ui/react';
17-
import type { OrgType } from '@fastgpt/global/support/user/team/org/type';
17+
import type { OrgListItemType, OrgType } from '@fastgpt/global/support/user/team/org/type';
1818
import Avatar from '@fastgpt/web/components/common/Avatar';
1919
import MyIcon from '@fastgpt/web/components/common/Icon';
2020
import type { IconNameType } from '@fastgpt/web/components/common/Icon/type';
@@ -23,9 +23,7 @@ import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
2323
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
2424
import { useTranslation } from 'next-i18next';
2525
import { useMemo, useState } from 'react';
26-
import { useContextSelector } from 'use-context-selector';
2726
import MemberTag from '@/components/support/user/team/Info/MemberTag';
28-
import { TeamContext } from '../context';
2927
import {
3028
deleteOrg,
3129
deleteOrgMember,
@@ -39,10 +37,10 @@ import { defaultOrgForm, type OrgFormType } from './OrgInfoModal';
3937
import dynamic from 'next/dynamic';
4038
import MyBox from '@fastgpt/web/components/common/MyBox';
4139
import Path from '@/components/common/folder/Path';
42-
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
40+
import { ParentIdType, ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
4341
import { getOrgChildrenPath } from '@fastgpt/global/support/user/team/org/constant';
4442
import { useSystemStore } from '@/web/common/system/useSystemStore';
45-
import { delRemoveMember, getTeamMembers } from '@/web/support/user/team/api';
43+
import { delRemoveMember } from '@/web/support/user/team/api';
4644
import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
4745
import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
4846

@@ -82,68 +80,52 @@ function ActionButton({
8280
function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
8381
const { t } = useTranslation();
8482
const { userInfo, isTeamAdmin } = useUserStore();
85-
const [searchOrg, setSearchOrg] = useState('');
86-
const [orgStack, setOrgStack] = useState<OrgType[]>([]);
87-
const currentOrg = useMemo(() => orgStack[orgStack.length - 1], [orgStack]);
88-
89-
const [rootOrg, setRootOrg] = useState<OrgType>();
83+
const { feConfigs } = useSystemStore();
84+
const isSyncMember = feConfigs.register_method?.includes('sync');
9085

91-
const { data: members = [], ScrollData: MemberScrollData } = useScrollPagination(getOrgMembers, {
92-
pageSize: 20,
93-
params: {
94-
orgId: currentOrg?._id ?? rootOrg?._id
95-
},
96-
refreshDeps: [currentOrg?._id, rootOrg?._id]
97-
});
86+
const [searchOrg, setSearchOrg] = useState('');
9887

99-
const { feConfigs } = useSystemStore();
88+
const [parentId, setParentId] = useState<ParentIdType>();
89+
const [currentOrg, setCurrentOrg] = useState<OrgListItemType>();
10090

101-
const isSyncMember = feConfigs.register_method?.includes('sync');
102-
const [path, setPath] = useState('');
91+
// 用于 org 层级
92+
const [orgStack, setOrgStack] = useState<OrgListItemType[]>([]);
10393

10494
const {
10595
data: orgs = [],
10696
loading: isLoadingOrgs,
10797
refresh: refetchOrgs
10898
} = useRequest2(
10999
() => {
110-
// sync path to orgStack
111-
const splitPath = path.split('/').filter(Boolean);
112-
const orgs = orgStack.filter((o) => splitPath.includes(o.pathId));
113-
setOrgStack(orgs);
114-
return getOrgList(path);
100+
return getOrgList(parentId);
115101
},
116102
{
117103
manual: false,
118-
refreshDeps: [userInfo?.team?.teamId, path],
119-
onSuccess: (data) => {
120-
if (!rootOrg) {
121-
setRootOrg(data[0]);
122-
}
123-
}
104+
refreshDeps: [userInfo?.team?.teamId, parentId]
124105
}
125106
);
126107

127108
const paths = useMemo(() => {
109+
if (!currentOrg) return [];
128110
return orgStack
129111
.map((org) => {
130-
if (org?.path === '') return;
131112
return {
132113
parentId: getOrgChildrenPath(org),
133114
parentName: org.name
134115
};
135116
})
136117
.filter(Boolean) as ParentTreePathItemType[];
137-
}, [orgStack]);
118+
}, [currentOrg, orgStack]);
138119

139-
const onClickOrg = (org: OrgType) => {
120+
const onClickOrg = (org: OrgListItemType) => {
121+
setParentId(currentOrg?._id);
140122
setOrgStack([...orgStack, org]);
141-
setPath(getOrgChildrenPath(org));
123+
setCurrentOrg(org);
142124
};
143125

144126
const [editOrg, setEditOrg] = useState<OrgFormType>();
145-
const [manageMemberOrg, setManageMemberOrg] = useState<OrgType>();
146-
const [movingOrg, setMovingOrg] = useState<OrgType>();
127+
const [manageMemberOrg, setManageMemberOrg] = useState<OrgListItemType>();
128+
const [movingOrg, setMovingOrg] = useState<OrgListItemType>();
147129

148130
// Delete org
149131
const { ConfirmModal: ConfirmDeleteOrgModal, openConfirm: openDeleteOrgModal } = useConfirm({
@@ -157,6 +139,14 @@ function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
157139
}
158140
});
159141

142+
const { data: members = [], ScrollData: MemberScrollData } = useScrollPagination(getOrgMembers, {
143+
pageSize: 20,
144+
params: {
145+
orgId: currentOrg?._id
146+
},
147+
refreshDeps: [currentOrg?._id]
148+
});
149+
160150
// Delete member
161151
const { ConfirmModal: ConfirmDeleteMemberFromOrg, openConfirm: openDeleteMemberFromOrgModal } =
162152
useConfirm({
@@ -183,11 +173,7 @@ function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
183173
const searchedOrgs = useMemo(() => {
184174
if (!searchOrg) return [];
185175

186-
return orgs
187-
.filter((org) => org.name.includes(searchOrg))
188-
.map((org) => ({
189-
...org
190-
}));
176+
return orgs.filter((org) => org.name.includes(searchOrg));
191177
}, [orgs, searchOrg]);
192178

193179
return (
@@ -231,7 +217,7 @@ function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
231217
<Tr key={org._id} overflow={'unset'} onClick={() => onClickOrg(org)}>
232218
<Td>
233219
<HStack cursor={'pointer'} onClick={() => onClickOrg(org)}>
234-
<MemberTag name={org.name} avatar={org.avatar} />
220+
<MemberTag name={org.name} avatar={org.avatar!} />
235221
<Tag size="sm">{org.total}</Tag>
236222
<MyIcon
237223
name="core/chat/chevronRight"
@@ -427,7 +413,7 @@ function OrgTable({ Tabs }: { Tabs: React.ReactNode }) {
427413
onClick={() => {
428414
setEditOrg({
429415
...defaultOrgForm,
430-
parentId: currentOrg?._id ?? rootOrg?._id
416+
parentId: currentOrg?._id
431417
});
432418
}}
433419
/>

0 commit comments

Comments
 (0)