{channelList.map((item) => {
- const providerData = aiproxyIdMap[item.type];
+ const providerData = aiproxyIdMap[item.type] || {
+ label: channelProviders[item.type]?.name || 'Invalid provider',
+ provider: 'Other'
+ };
const provider = getModelProvider(providerData?.provider);
return (
@@ -119,14 +136,10 @@ const ChannelTable = ({ Tab }: { Tab: React.ReactNode }) => {
{item.id} |
{item.name} |
- {providerData ? (
-
-
- {t(providerData?.label as any)}
-
- ) : (
- 'Invalid provider'
- )}
+
+
+ {t(providerData?.label as any)}
+
|
{
type: 'danger',
icon: 'delete',
label: t('common:common.Delete'),
- onClick: () => onDeleteChannel(item.id)
+ onClick: () =>
+ openConfirm(
+ () => onDeleteChannel(item.id),
+ undefined,
+ t('account_model:confirm_delete_channel', {
+ name: item.name
+ })
+ )()
}
]
}
@@ -229,6 +249,7 @@ const ChannelTable = ({ Tab }: { Tab: React.ReactNode }) => {
{!!modelTestData && (
setTestModelData(undefined)} />
)}
+
>
);
};
diff --git a/projects/app/src/pageComponents/account/model/Log/index.tsx b/projects/app/src/pageComponents/account/model/Log/index.tsx
index afe811895..26e3dd39a 100644
--- a/projects/app/src/pageComponents/account/model/Log/index.tsx
+++ b/projects/app/src/pageComponents/account/model/Log/index.tsx
@@ -33,6 +33,7 @@ import { formatTime2YMDHMS } from '@fastgpt/global/common/string/time';
import MyModal from '@fastgpt/web/components/common/MyModal';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
+import { ChannelLogUsageType } from '@/global/aiproxy/type';
type LogDetailType = {
id: number;
@@ -42,10 +43,10 @@ type LogDetailType = {
duration: number;
request_at: string;
code: number;
- prompt_tokens: number;
- completion_tokens: number;
+ usage?: ChannelLogUsageType;
endpoint: string;
+ retry_times?: number;
content?: string;
request_body?: string;
response_body?: string;
@@ -159,8 +160,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => {
duration: durationSecond,
request_at: formatTime2YMDHMS(item.request_at),
code: item.code,
- prompt_tokens: item.prompt_tokens,
- completion_tokens: item.completion_tokens,
+ usage: item.usage,
request_id: item.request_id,
endpoint: item.endpoint,
content: item.content
@@ -197,7 +197,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => {
/>
-
+
{t('account_model:channel_name')}
@@ -210,7 +210,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => {
/>
-
+
{t('account_model:model_name')}
@@ -260,7 +260,7 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => {
{item.channelName} |
{item.model} |
- {item.prompt_tokens} / {item.completion_tokens}
+ {item.usage?.input_tokens} / {item.usage?.output_tokens}
|
10 ? 'red.600' : ''}>{item.duration.toFixed(2)}s |
@@ -297,6 +297,7 @@ const LogDetail = ({ data, onClose }: { data: LogDetailType; onClose: () => void
const { t } = useTranslation();
const { data: detailData } = useRequest2(
async () => {
+ console.log(data);
if (data.code === 200) return data;
try {
const res = await getLogDetail(data.id);
@@ -363,7 +364,7 @@ const LogDetail = ({ data, onClose }: { data: LogDetailType; onClose: () => void
RequestID
{detailData?.request_id}
-
+
{t('account_model:channel_status')}
{detailData?.code}
@@ -373,7 +374,7 @@ const LogDetail = ({ data, onClose }: { data: LogDetailType; onClose: () => void
Endpoint
{detailData?.endpoint}
-
+
{t('account_model:channel_name')}
{detailData?.channelName}
@@ -381,7 +382,7 @@ const LogDetail = ({ data, onClose }: { data: LogDetailType; onClose: () => void
{t('account_model:request_at')}
{detailData?.request_at}
-
+
{t('account_model:duration')}
{detailData?.duration.toFixed(2)}s
@@ -389,20 +390,26 @@ const LogDetail = ({ data, onClose }: { data: LogDetailType; onClose: () => void
{t('account_model:model')}
{detailData?.model}
-
+
{t('account_model:model_tokens')}
- {detailData?.prompt_tokens} / {detailData?.completion_tokens}
+ {detailData?.usage?.input_tokens} / {detailData?.usage?.output_tokens}
+ {detailData?.retry_times !== undefined && (
+
+ {t('account_model:retry_times')}
+ {detailData?.retry_times}
+
+ )}
{detailData?.content && (
-
+
Content
{detailData?.content}
)}
{detailData?.request_body && (
-
+
Request Body
{detailData?.request_body}
diff --git a/projects/app/src/pageComponents/account/team/EditInfoModal.tsx b/projects/app/src/pageComponents/account/team/EditInfoModal.tsx
index c42ceaa90..f6ac3faf6 100644
--- a/projects/app/src/pageComponents/account/team/EditInfoModal.tsx
+++ b/projects/app/src/pageComponents/account/team/EditInfoModal.tsx
@@ -117,7 +117,7 @@ function EditModal({
ml={4}
autoFocus
bg={'myWhite.600'}
- maxLength={20}
+ maxLength={100}
placeholder={t('user:team.Team Name')}
{...register('name', {
required: t('common:common.Please Input Name')
diff --git a/projects/app/src/pageComponents/account/team/GroupManage/GroupInfoModal.tsx b/projects/app/src/pageComponents/account/team/GroupManage/GroupInfoModal.tsx
index 9fd81a310..22382e2c6 100644
--- a/projects/app/src/pageComponents/account/team/GroupManage/GroupInfoModal.tsx
+++ b/projects/app/src/pageComponents/account/team/GroupManage/GroupInfoModal.tsx
@@ -2,25 +2,31 @@ import { Input, HStack, ModalBody, Button, ModalFooter } from '@chakra-ui/react'
import MyModal from '@fastgpt/web/components/common/MyModal';
import Avatar from '@fastgpt/web/components/common/Avatar';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
-
import { useTranslation } from 'next-i18next';
-import React, { useMemo } from 'react';
+import React from 'react';
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useForm } from 'react-hook-form';
-import { useContextSelector } from 'use-context-selector';
-import { TeamContext } from '../context';
import { postCreateGroup, putUpdateGroup } from '@/web/support/user/team/group/api';
import { DEFAULT_TEAM_AVATAR } from '@fastgpt/global/common/system/constants';
+import { MemberGroupListItemType } from '@fastgpt/global/support/permission/memberGroup/type';
export type GroupFormType = {
avatar: string;
name: string;
};
-function GroupInfoModal({ onClose, editGroupId }: { onClose: () => void; editGroupId?: string }) {
- const { refetchGroups, groups, refetchMembers } = useContextSelector(TeamContext, (v) => v);
+function GroupInfoModal({
+ onClose,
+ editGroup,
+ onSuccess
+}: {
+ onClose: () => void;
+ editGroup?: MemberGroupListItemType;
+ onSuccess: () => void;
+}) {
const { t } = useTranslation();
+
const {
File: AvatarSelect,
onOpen: onOpenSelectAvatar,
@@ -30,14 +36,10 @@ function GroupInfoModal({ onClose, editGroupId }: { onClose: () => void; editGro
multiple: false
});
- const group = useMemo(() => {
- return groups.find((item) => item._id === editGroupId);
- }, [editGroupId, groups]);
-
const { register, handleSubmit, getValues, setValue } = useForm({
defaultValues: {
- name: group?.name || '',
- avatar: group?.avatar || DEFAULT_TEAM_AVATAR
+ name: editGroup?.name || '',
+ avatar: editGroup?.avatar || DEFAULT_TEAM_AVATAR
}
});
@@ -63,21 +65,21 @@ function GroupInfoModal({ onClose, editGroupId }: { onClose: () => void; editGro
});
},
{
- onSuccess: () => Promise.all([onClose(), refetchGroups(), refetchMembers()])
+ onSuccess: () => Promise.all([onClose(), onSuccess()])
}
);
const { runAsync: onUpdate, loading: isLoadingUpdate } = useRequest2(
async (data: GroupFormType) => {
- if (!editGroupId) return;
+ if (!editGroup) return;
return putUpdateGroup({
- groupId: editGroupId,
+ groupId: editGroup._id,
name: data.name,
avatar: data.avatar
});
},
{
- onSuccess: () => Promise.all([onClose(), refetchGroups(), refetchMembers()])
+ onSuccess: () => Promise.all([onClose(), onSuccess()])
}
);
@@ -86,8 +88,8 @@ function GroupInfoModal({ onClose, editGroupId }: { onClose: () => void; editGro
return (
{t('user:team.avatar_and_name')}
@@ -109,14 +111,14 @@ function GroupInfoModal({ onClose, editGroupId }: { onClose: () => void; editGro
diff --git a/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx b/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx
index fbd8df13b..f7005b35c 100644
--- a/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx
+++ b/projects/app/src/pageComponents/account/team/GroupManage/GroupManageMember.tsx
@@ -1,29 +1,25 @@
-import {
- Box,
- ModalBody,
- Flex,
- Button,
- ModalFooter,
- Checkbox,
- Grid,
- HStack
-} from '@chakra-ui/react';
+import { Box, ModalBody, Flex, Button, ModalFooter, Grid, HStack } from '@chakra-ui/react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@fastgpt/web/components/common/Avatar';
import Tag from '@fastgpt/web/components/common/Tag';
import { useTranslation } from 'next-i18next';
-import React, { useMemo, useRef, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
-import { useContextSelector } from 'use-context-selector';
-import { TeamContext } from '../context';
import { putUpdateGroup } from '@/web/support/user/team/group/api';
import { GroupMemberRole } from '@fastgpt/global/support/permission/memberGroup/constant';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { DEFAULT_TEAM_AVATAR } from '@fastgpt/global/common/system/constants';
import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
+import { MemberGroupListItemType } from '@fastgpt/global/support/permission/memberGroup/type';
+import { getTeamMembers } from '@/web/support/user/team/api';
+import { TeamMemberItemType } from '@fastgpt/global/support/user/team/type';
+import { PaginationResponse } from '@fastgpt/web/common/fetch/type';
+import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
+import _ from 'lodash';
+import MemberItemCard from '@/components/support/permission/MemberManager/MemberItemCard';
export type GroupFormType = {
members: {
@@ -35,63 +31,100 @@ export type GroupFormType = {
// 1. Owner can not be deleted, toast
// 2. Owner/Admin can manage members
// 3. Owner can add/remove admins
-function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGroupId?: string }) {
+function GroupEditModal({
+ onClose,
+ group,
+ onSuccess
+}: {
+ onClose: () => void;
+ group: MemberGroupListItemType;
+ onSuccess: () => void;
+}) {
const { t } = useTranslation();
const { userInfo } = useUserStore();
const { toast } = useToast();
- const groups = useContextSelector(TeamContext, (v) => v.groups);
- const refetchGroups = useContextSelector(TeamContext, (v) => v.refetchGroups);
- const group = useMemo(() => {
- return groups.find((item) => item._id === editGroupId);
- }, [editGroupId, groups]);
-
- const allMembers = useContextSelector(TeamContext, (v) => v.members);
- const refetchMembers = useContextSelector(TeamContext, (v) => v.refetchMembers);
- const MemberScrollData = useContextSelector(TeamContext, (v) => v.MemberScrollData);
- const [hoveredMemberId, setHoveredMemberId] = useState();
-
- const selectedMembersRef = useRef(null);
- const [members, setMembers] = useState(group?.members || []);
-
const [searchKey, setSearchKey] = useState('');
- const filtered = useMemo(() => {
- return [
- ...allMembers.filter((member) => {
- if (member.memberName.toLowerCase().includes(searchKey.toLowerCase())) return true;
- return false;
- })
- ];
- }, [searchKey, allMembers]);
+ const [selected, setSelected] = useState<
+ { name: string; tmbId: string; avatar: string; role: `${GroupMemberRole}` }[]
+ >([]);
+
+ const {
+ data: allMembers = [],
+ ScrollData: MemberScrollData,
+ refreshList
+ } = useScrollPagination<
+ any,
+ PaginationResponse>
+ >(getTeamMembers, {
+ pageSize: 20,
+ params: {
+ status: 'active',
+ withOrgs: true,
+ searchKey
+ },
+ throttleWait: 500,
+ debounceWait: 200,
+ refreshDeps: [searchKey]
+ });
+
+ const groupId = useMemo(() => String(group._id), [group._id]);
+
+ const { data: groupMembers = [], ScrollData: GroupScrollData } = useScrollPagination<
+ any,
+ PaginationResponse<
+ TeamMemberItemType<{ withOrgs: true; withPermission: true; withGroupRole: true }>
+ >
+ >(getTeamMembers, {
+ pageSize: 100000,
+ params: {
+ groupId: groupId
+ }
+ });
+
+ useEffect(() => {
+ if (!groupId) return;
+ setSelected(
+ groupMembers.map((item) => ({
+ name: item.memberName,
+ tmbId: item.tmbId,
+ avatar: item.avatar,
+ role: (item.groupRole ?? 'member') as `${GroupMemberRole}`
+ }))
+ );
+ }, [groupId, groupMembers]);
+
+ const [hoveredMemberId, setHoveredMemberId] = useState();
const { runAsync: onUpdate, loading: isLoadingUpdate } = useRequest2(
async () => {
- if (!editGroupId || !members.length) return;
+ if (!group._id || !groupMembers.length) return;
+
return putUpdateGroup({
- groupId: editGroupId,
- memberList: members
+ groupId: group._id,
+ memberList: selected
});
},
{
- onSuccess: () => Promise.all([onClose(), refetchGroups(), refetchMembers()])
+ onSuccess: () => Promise.all([onClose(), onSuccess()])
}
);
const isSelected = (memberId: string) => {
- return members.find((item) => item.tmbId === memberId);
+ return selected.find((item) => item.tmbId === memberId);
};
const myRole = useMemo(() => {
if (userInfo?.team.permission.hasManagePer) {
return 'owner';
}
- return members.find((item) => item.tmbId === userInfo?.team.tmbId)?.role ?? 'member';
- }, [members, userInfo]);
+ return groupMembers.find((item) => item.tmbId === userInfo?.team.tmbId)?.groupRole ?? 'member';
+ }, [groupMembers, userInfo]);
const handleToggleSelect = (memberId: string) => {
if (
myRole === 'owner' &&
- memberId === group?.members.find((item) => item.role === 'owner')?.tmbId
+ memberId === groupMembers.find((item) => item.role === 'owner')?.tmbId
) {
toast({
title: t('user:team.group.toast.can_not_delete_owner'),
@@ -102,28 +135,38 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
if (
myRole === 'admin' &&
- group?.members.find((item) => String(item.tmbId) === memberId)?.role !== 'member'
+ selected.find((item) => String(item.tmbId) === memberId)?.role !== 'member'
) {
return;
}
if (isSelected(memberId)) {
- setMembers(members.filter((item) => item.tmbId !== memberId));
+ setSelected(selected.filter((item) => item.tmbId !== memberId));
} else {
- setMembers([...members, { tmbId: memberId, role: 'member' }]);
+ const member = allMembers.find((m) => m.tmbId === memberId);
+ if (!member) return;
+ setSelected([
+ ...selected,
+ {
+ name: member.memberName,
+ avatar: member.avatar,
+ tmbId: member.tmbId,
+ role: 'member'
+ }
+ ]);
}
};
const handleToggleAdmin = (memberId: string) => {
if (myRole === 'owner' && isSelected(memberId)) {
- const oldRole = members.find((item) => item.tmbId === memberId)?.role;
+ const oldRole = groupMembers.find((item) => item.tmbId === memberId)?.groupRole;
if (oldRole === 'admin') {
- setMembers(
- members.map((item) => (item.tmbId === memberId ? { ...item, role: 'member' } : item))
+ setSelected(
+ selected.map((item) => (item.tmbId === memberId ? { ...item, role: 'member' } : item))
);
} else {
- setMembers(
- members.map((item) => (item.tmbId === memberId ? { ...item, role: 'admin' } : item))
+ setSelected(
+ selected.map((item) => (item.tmbId === memberId ? { ...item, role: 'admin' } : item))
);
}
}
@@ -158,37 +201,24 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
}}
/>
- {filtered.map((member) => {
+ {allMembers.map((member) => {
return (
- handleToggleSelect(member.tmbId)}
- >
- }
- />
-
- {member.memberName}
-
+ name={member.memberName}
+ onChange={() => handleToggleSelect(member.tmbId)}
+ isChecked={!!isSelected(member.tmbId)}
+ orgs={member.orgs}
+ />
);
})}
- {t('common:chosen') + ': ' + members.length}
-
- {members.map((member) => {
+ {t('common:chosen') + ': ' + selected.length}
+
+ {selected.map((member) => {
return (
setHoveredMemberId(member.tmbId)}
@@ -202,14 +232,8 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
_notLast={{ mb: 2 }}
>
- item.tmbId === member.tmbId)?.avatar}
- w="1.5rem"
- borderRadius={'md'}
- />
-
- {allMembers.find((item) => item.tmbId === member.tmbId)?.memberName}
-
+
+ {member.name}
{(() => {
@@ -264,7 +288,7 @@ function GroupEditModal({ onClose, editGroupId }: { onClose: () => void; editGro
);
})}
-
+
diff --git a/projects/app/src/pageComponents/account/team/GroupManage/GroupTransferOwnerModal.tsx b/projects/app/src/pageComponents/account/team/GroupManage/GroupTransferOwnerModal.tsx
index 3a583fbf0..8365c25d7 100644
--- a/projects/app/src/pageComponents/account/team/GroupManage/GroupTransferOwnerModal.tsx
+++ b/projects/app/src/pageComponents/account/team/GroupManage/GroupTransferOwnerModal.tsx
@@ -1,4 +1,4 @@
-import { putUpdateGroup } from '@/web/support/user/team/group/api';
+import { putGroupChangeOwner } from '@/web/support/user/team/group/api';
import {
Box,
Flex,
@@ -15,34 +15,46 @@ import Avatar from '@fastgpt/web/components/common/Avatar';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useTranslation } from 'next-i18next';
-import React, { useMemo, useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { TeamContext } from '../context';
import { useContextSelector } from 'use-context-selector';
-
-export type ChangeOwnerModalProps = {
- groupId: string;
-};
+import { MemberGroupListItemType } from '@fastgpt/global/support/permission/memberGroup/type';
+import { GetSearchUserGroupOrg } from '@/web/support/user/api';
+import { Omit } from '@fastgpt/web/components/common/DndDrag';
+import { getTeamMembers } from '@/web/support/user/team/api';
+import { PaginationResponse } from '@fastgpt/web/common/fetch/type';
+import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
+import _ from 'lodash';
export function ChangeOwnerModal({
- onClose,
- groupId
-}: ChangeOwnerModalProps & { onClose: () => void }) {
+ group,
+ onSuccess,
+ onClose
+}: {
+ group: MemberGroupListItemType;
+ onSuccess: () => void;
+ onClose: () => void;
+}) {
const { t } = useTranslation();
- const [inputValue, setInputValue] = React.useState('');
- const { members: allMembers, groups, refetchGroups } = useContextSelector(TeamContext, (v) => v);
- const group = useMemo(() => {
- return groups.find((item) => item._id === groupId);
- }, [groupId, groups]);
- const memberList = allMembers.filter((item) => {
- return item.memberName.toLowerCase().includes(inputValue.toLowerCase());
- });
+ const [searchKey, setSearchKey] = React.useState('');
- const OldOwnerId = useMemo(() => {
- return group?.members.find((item) => item.role === 'owner')?.tmbId;
- }, [group]);
-
- const [keepAdmin, setKeepAdmin] = useState(true);
+ const {
+ data: members = [],
+ ScrollData: MemberScrollData,
+ refreshList
+ } = useScrollPagination>>(
+ getTeamMembers,
+ {
+ pageSize: 20,
+ params: {
+ searchKey
+ },
+ refreshDeps: [searchKey],
+ debounceWait: 200,
+ throttleWait: 500
+ }
+ );
const {
isOpen: isOpenMemberListMenu,
@@ -50,44 +62,27 @@ export function ChangeOwnerModal({
onOpen: onOpenMemberListMenu
} = useDisclosure();
- const [selectedMember, setSelectedMember] = useState(null);
+ const [selectedMember, setSelectedMember] = useState | null>(null);
- const onChangeOwner = async (tmbId: string) => {
- if (!group) {
- return;
+ const [keepAdmin, setKeepAdmin] = useState(true);
+
+ const { runAsync: onTransfer, loading } = useRequest2(
+ (tmbId: string) => putGroupChangeOwner(group._id, tmbId),
+ {
+ onSuccess: () => Promise.all([onClose(), onSuccess()]),
+ successToast: t('common:permission.change_owner_success'),
+ errorToast: t('common:permission.change_owner_failed')
}
-
- const newMemberList = group.members
- .map((item) => {
- if (item.tmbId === OldOwnerId) {
- if (keepAdmin) {
- return { tmbId: OldOwnerId, role: 'admin' };
- }
- return { tmbId: OldOwnerId, role: 'member' };
- }
- return item;
- })
- .filter((item) => item.tmbId !== tmbId) as any;
-
- newMemberList.push({ tmbId, role: 'owner' });
-
- return putUpdateGroup({
- groupId,
- memberList: newMemberList
- });
- };
-
- const { runAsync, loading } = useRequest2(onChangeOwner, {
- onSuccess: () => Promise.all([onClose(), refetchGroups()]),
- successToast: t('common:permission.change_owner_success'),
- errorToast: t('common:permission.change_owner_failed')
- });
+ );
const onConfirm = async () => {
if (!selectedMember) {
return;
}
- await runAsync(selectedMember.tmbId);
+ await onTransfer(selectedMember.tmbId);
};
return (
@@ -97,7 +92,6 @@ export function ChangeOwnerModal({
iconColor="primary.600"
onClose={onClose}
title={t('common:permission.change_owner')}
- isLoading={loading}
>
@@ -120,9 +114,9 @@ export function ChangeOwnerModal({
)}
{
- setInputValue(e.target.value);
+ setSearchKey(e.target.value);
setSelectedMember(null);
}}
onFocus={() => {
@@ -132,7 +126,7 @@ export function ChangeOwnerModal({
{...(selectedMember && { pl: '10' })}
/>
- {isOpenMemberListMenu && memberList.length > 0 && (
+ {isOpenMemberListMenu && members.length > 0 && (
- {memberList.map((item) => (
- {
- setInputValue(item.memberName);
- setSelectedMember(item);
- onCloseMemberListMenu();
- }}
- >
-
-
- {item.memberName}
-
-
- ))}
+
+ {members.map((item) => (
+ {
+ setSearchKey(item.memberName);
+ setSelectedMember(item);
+ onCloseMemberListMenu();
+ }}
+ >
+
+
+ {item.memberName}
+
+
+ ))}
+
)}
@@ -186,7 +182,9 @@ export function ChangeOwnerModal({
-
+
diff --git a/projects/app/src/pageComponents/account/team/GroupManage/index.tsx b/projects/app/src/pageComponents/account/team/GroupManage/index.tsx
index dc9ae458c..78bb0d60c 100644
--- a/projects/app/src/pageComponents/account/team/GroupManage/index.tsx
+++ b/projects/app/src/pageComponents/account/team/GroupManage/index.tsx
@@ -3,7 +3,6 @@ import {
Box,
Button,
Flex,
- HStack,
Table,
TableContainer,
Tbody,
@@ -16,20 +15,18 @@ import {
import { useTranslation } from 'next-i18next';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import MyBox from '@fastgpt/web/components/common/MyBox';
-import { useContextSelector } from 'use-context-selector';
-import { TeamContext } from '../context';
import MyMenu, { MenuItemType } from '@fastgpt/web/components/common/MyMenu';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useUserStore } from '@/web/support/user/useUserStore';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
-import { deleteGroup } from '@/web/support/user/team/group/api';
+import { deleteGroup, getGroupList } from '@/web/support/user/team/group/api';
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
import MemberTag from '../../../../components/support/user/team/Info/MemberTag';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import dynamic from 'next/dynamic';
import { useState } from 'react';
import IconButton from '../OrgManage/IconButton';
-import { MemberGroupType } from '@fastgpt/global/support/permission/memberGroup/type';
+import { MemberGroupListItemType } from '@fastgpt/global/support/permission/memberGroup/type';
const ChangeOwnerModal = dynamic(() => import('./GroupTransferOwnerModal'));
const GroupInfoModal = dynamic(() => import('./GroupInfoModal'));
@@ -39,19 +36,23 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
const { t } = useTranslation();
const { userInfo } = useUserStore();
- const { groups, refetchGroups, members, refetchMembers } = useContextSelector(
- TeamContext,
- (v) => v
- );
+ const {
+ data: groups = [],
+ loading: isLoadingGroups,
+ refresh: refetchGroups
+ } = useRequest2(() => getGroupList({ withMembers: true }), {
+ manual: false,
+ refreshDeps: [userInfo?.team?.teamId]
+ });
+
+ const [editGroup, setEditGroup] = useState>();
- const [editGroup, setEditGroup] = useState();
const {
isOpen: isOpenGroupInfo,
onOpen: onOpenGroupInfo,
onClose: onCloseGroupInfo
} = useDisclosure();
-
- const onEditGroupInfo = (e: MemberGroupType) => {
+ const onEditGroupInfo = (e: MemberGroupListItemType) => {
setEditGroup(e);
onOpenGroupInfo();
};
@@ -60,11 +61,9 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
type: 'delete',
content: t('account_team:confirm_delete_group')
});
-
const { runAsync: delDeleteGroup } = useRequest2(deleteGroup, {
onSuccess: () => {
refetchGroups();
- refetchMembers();
}
});
@@ -73,26 +72,17 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
onOpen: onOpenManageGroupMember,
onClose: onCloseManageGroupMember
} = useDisclosure();
- const onManageMember = (e: MemberGroupType) => {
+ const onManageMember = (e: MemberGroupListItemType) => {
setEditGroup(e);
onOpenManageGroupMember();
};
- const hasGroupManagePer = (group: (typeof groups)[0]) =>
- userInfo?.team.permission.hasManagePer ||
- ['admin', 'owner'].includes(
- group.members.find((item) => item.tmbId === userInfo?.team.tmbId)?.role ?? ''
- );
- const isGroupOwner = (group: (typeof groups)[0]) =>
- userInfo?.team.permission.hasManagePer ||
- group.members.find((item) => item.role === 'owner')?.tmbId === userInfo?.team.tmbId;
-
const {
isOpen: isOpenChangeOwner,
onOpen: onOpenChangeOwner,
onClose: onCloseChangeOwner
} = useDisclosure();
- const onChangeOwner = (e: MemberGroupType) => {
+ const onChangeOwner = (e: MemberGroupListItemType) => {
setEditGroup(e);
onOpenChangeOwner();
};
@@ -115,7 +105,7 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
)}
-
+
@@ -133,66 +123,38 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
{groups?.map((group) => (
-
-
-
-
- ({group.name === DefaultGroupName ? members.length : group.members.length})
-
-
- |
item.role === 'owner')?.memberName ?? ''
- : members.find(
- (item) =>
- item.tmbId ===
- group.members.find((item) => item.role === 'owner')?.tmbId
- )?.memberName ?? ''
- }
- avatar={
- group.name === DefaultGroupName
- ? members.find((item) => item.role === 'owner')?.avatar ?? ''
- : members.find(
- (i) =>
- i.tmbId ===
- group.members.find((item) => item.role === 'owner')?.tmbId
- )?.avatar ?? ''
+ group.name === DefaultGroupName ? userInfo?.team.teamName ?? '' : group.name
}
+ avatar={group.avatar}
/>
|
- {group.name === DefaultGroupName ? (
- v.avatar)} />
- ) : hasGroupManagePer(group) ? (
-
- onManageMember(group)}>
- members.find((m) => m.tmbId === v.tmbId)?.avatar ?? ''
- )}
- />
-
-
- ) : (
- members.find((m) => m.tmbId === v.tmbId)?.avatar ?? ''
- )}
- />
- )}
+
|
- {hasGroupManagePer(group) && group.name !== DefaultGroupName && (
+
+ onManageMember(group)
+ }
+ : {})}
+ >
+ v.avatar)}
+ total={group.count}
+ />
+
+
+ |
+
+ {group.permission?.hasManagePer && (
}
menuList={[
@@ -212,7 +174,7 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
onManageMember(group);
}
},
- ...(isGroupOwner(group)
+ ...(group.permission?.isOwner
? [
{
label: t('account_team:transfer_ownership'),
@@ -246,25 +208,33 @@ function MemberTable({ Tabs }: { Tabs: React.ReactNode }) {
- {isOpenChangeOwner && editGroup && (
-
- )}
+
{isOpenGroupInfo && (
{
onCloseGroupInfo();
setEditGroup(undefined);
}}
- editGroupId={editGroup?._id}
/>
)}
+ {isOpenChangeOwner && editGroup && (
+
+ )}
+
{isOpenManageGroupMember && editGroup && (
{
onCloseManageGroupMember();
setEditGroup(undefined);
}}
- editGroupId={editGroup._id}
+ onSuccess={refetchGroups}
/>
)}
>
diff --git a/projects/app/src/pageComponents/account/team/Invite/CreateInvitationModal.tsx b/projects/app/src/pageComponents/account/team/Invite/CreateInvitationModal.tsx
index 8f1d43a3c..451b0f7ce 100644
--- a/projects/app/src/pageComponents/account/team/Invite/CreateInvitationModal.tsx
+++ b/projects/app/src/pageComponents/account/team/Invite/CreateInvitationModal.tsx
@@ -22,7 +22,13 @@ import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useTranslation } from 'next-i18next';
import { useForm } from 'react-hook-form';
-function CreateInvitationModal({ onClose }: { onClose: () => void }) {
+function CreateInvitationModal({
+ onSuccess,
+ onClose
+}: {
+ onSuccess: (linkId: string) => void;
+ onClose: () => void;
+}) {
const { t } = useTranslation();
const expiresOptions: Array<{ label: string; value: InvitationLinkExpiresType }> = [
{ label: t('account_team:30mins'), value: '30m' }, // 30 mins
@@ -43,9 +49,11 @@ function CreateInvitationModal({ onClose }: { onClose: () => void }) {
const { runAsync: createInvitationLink, loading } = useRequest2(postCreateInvitationLink, {
manual: true,
- successToast: t('common:common.Create Success'),
errorToast: t('common:common.Create Failed'),
- onFinally: () => onClose()
+ onSuccess: (data) => {
+ onSuccess(data);
+ onClose();
+ }
});
return (
@@ -55,7 +63,7 @@ function CreateInvitationModal({ onClose }: { onClose: () => void }) {
iconColor="primary.500"
title={{t('account_team:create_invitation_link')}}
>
-
+ onClose()} />
<>
@@ -91,7 +99,7 @@ function CreateInvitationModal({ onClose }: { onClose: () => void }) {
- | | |