diff --git a/packages/global/common/error/code/team.ts b/packages/global/common/error/code/team.ts index 30ab14fc5..7c2ab6790 100644 --- a/packages/global/common/error/code/team.ts +++ b/packages/global/common/error/code/team.ts @@ -2,6 +2,7 @@ import { i18nT } from '../../../../web/i18n/utils'; import type { ErrType } from '../errorCode'; /* team: 500000 */ export enum TeamErrEnum { + notUser = 'notUser', teamOverSize = 'teamOverSize', unAuthTeam = 'unAuthTeam', teamMemberOverSize = 'teamMemberOverSize', @@ -27,6 +28,10 @@ export enum TeamErrEnum { } const teamErr = [ + { + statusText: TeamErrEnum.notUser, + message: i18nT('common:code_error.team_error.not_user') + }, { statusText: TeamErrEnum.teamOverSize, message: i18nT('common:code_error.team_error.over_size') diff --git a/packages/global/common/system/constants.ts b/packages/global/common/system/constants.ts index 6647317fe..4dcc4d276 100644 --- a/packages/global/common/system/constants.ts +++ b/packages/global/common/system/constants.ts @@ -1,7 +1,9 @@ export const HUMAN_ICON = `/icon/human.svg`; export const LOGO_ICON = `/icon/logo.svg`; export const HUGGING_FACE_ICON = `/imgs/model/huggingface.svg`; + export const DEFAULT_TEAM_AVATAR = `/imgs/avatar/defaultTeamAvatar.svg`; export const DEFAULT_ORG_AVATAR = '/imgs/avatar/defaultOrgAvatar.svg'; +export const DEFAULT_USER_AVATAR = '/imgs/avatar/BlueAvatar.svg'; export const isProduction = process.env.NODE_ENV === 'production'; diff --git a/packages/service/support/permission/controller.ts b/packages/service/support/permission/controller.ts index d944efba1..f233c66b1 100644 --- a/packages/service/support/permission/controller.ts +++ b/packages/service/support/permission/controller.ts @@ -153,7 +153,7 @@ export const getClbsAndGroupsWithInfo = async ({ }) .populate<{ tmb: TeamMemberSchema & { user: UserModelSchema } }>({ path: 'tmb', - select: 'name userId', + select: 'name userId role', populate: { path: 'user', select: 'avatar' diff --git a/packages/service/support/permission/org/controllers.ts b/packages/service/support/permission/org/controllers.ts index a19c0e7c6..ce0746055 100644 --- a/packages/service/support/permission/org/controllers.ts +++ b/packages/service/support/permission/org/controllers.ts @@ -4,7 +4,6 @@ import type { ClientSession } from 'mongoose'; import { MongoOrgModel } from './orgSchema'; import { MongoOrgMemberModel } from './orgMemberSchema'; import { getOrgChildrenPath } from '@fastgpt/global/support/user/team/org/constant'; -import { getNanoid } from '@fastgpt/global/common/string/tools'; export const getOrgsByTmbId = async ({ teamId, tmbId }: { teamId: string; tmbId: string }) => MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId').lean(); @@ -16,23 +15,29 @@ export const getOrgIdSetWithParentByTmbId = async ({ teamId: string; tmbId: string; }) => { - const orgMembers = await MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId') - .populate<{ org: { path: string } }>('org', 'path') - .lean(); + const orgMembers = await MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId').lean(); - const orgIds = new Set(); + const orgIds = Array.from(new Set(orgMembers.map((item) => String(item.orgId)))); + const orgs = await MongoOrgModel.find({ _id: { $in: orgIds } }, 'path').lean(); - for (const orgMember of orgMembers) { - orgIds.add(String(orgMember.orgId)); + const pathIdList = new Set( + orgs + .map((org) => { + const pathIdList = org.path.split('/').filter(Boolean); + return pathIdList; + }) + .flat() + ); + const parentOrgs = await MongoOrgModel.find( + { + teamId, + pathId: { $in: Array.from(pathIdList) } + }, + '_id' + ).lean(); + const parentOrgIds = parentOrgs.map((item) => String(item._id)); - // Add parent org - const parentIds = orgMember.org.path.split('/').filter(Boolean); - for (const parentId of parentIds) { - orgIds.add(parentId); - } - } - - return orgIds; + return new Set([...orgIds, ...parentOrgIds]); }; export const getChildrenByOrg = async ({ diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index 442a44fb1..15c87b98d 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -349,6 +349,8 @@ export const iconPaths = { history: () => import('./icons/history.svg'), infoRounded: () => import('./icons/infoRounded.svg'), kbTest: () => import('./icons/kbTest.svg'), + key: () => import('./icons/key.svg'), + keyPrimary: () => import('./icons/keyPrimary.svg'), menu: () => import('./icons/menu.svg'), minus: () => import('./icons/minus.svg'), 'modal/AddClb': () => import('./icons/modal/AddClb.svg'), @@ -360,7 +362,6 @@ export const iconPaths = { 'modal/selectSource': () => import('./icons/modal/selectSource.svg'), 'modal/setting': () => import('./icons/modal/setting.svg'), 'modal/teamPlans': () => import('./icons/modal/teamPlans.svg'), - 'modal/key': () => import('./icons/modal/key.svg'), 'model/BAAI': () => import('./icons/model/BAAI.svg'), 'model/alicloud': () => import('./icons/model/alicloud.svg'), 'model/baichuan': () => import('./icons/model/baichuan.svg'), @@ -412,7 +413,6 @@ export const iconPaths = { 'support/bill/shoppingCart': () => import('./icons/support/bill/shoppingCart.svg'), 'support/bill/wallet': () => import('./icons/support/bill/wallet.svg'), 'support/outlink/apikeyFill': () => import('./icons/support/outlink/apikeyFill.svg'), - 'support/outlink/apikeyLight': () => import('./icons/support/outlink/apikeyLight.svg'), 'support/outlink/iframeLight': () => import('./icons/support/outlink/iframeLight.svg'), 'support/outlink/share': () => import('./icons/support/outlink/share.svg'), 'support/outlink/shareLight': () => import('./icons/support/outlink/shareLight.svg'), @@ -420,7 +420,6 @@ export const iconPaths = { 'support/permission/privateLight': () => import('./icons/support/permission/privateLight.svg'), 'support/permission/publicLight': () => import('./icons/support/permission/publicLight.svg'), 'support/team/group': () => import('./icons/support/team/group.svg'), - 'support/team/key': () => import('./icons/support/team/key.svg'), 'support/team/memberLight': () => import('./icons/support/team/memberLight.svg'), 'support/usage/usageRecordLight': () => import('./icons/support/usage/usageRecordLight.svg'), 'support/user/informLight': () => import('./icons/support/user/informLight.svg'), diff --git a/packages/web/components/common/Icon/icons/support/team/key.svg b/packages/web/components/common/Icon/icons/key.svg similarity index 100% rename from packages/web/components/common/Icon/icons/support/team/key.svg rename to packages/web/components/common/Icon/icons/key.svg diff --git a/packages/web/components/common/Icon/icons/modal/key.svg b/packages/web/components/common/Icon/icons/keyPrimary.svg similarity index 100% rename from packages/web/components/common/Icon/icons/modal/key.svg rename to packages/web/components/common/Icon/icons/keyPrimary.svg diff --git a/packages/web/components/common/Icon/icons/support/outlink/apikeyLight.svg b/packages/web/components/common/Icon/icons/support/outlink/apikeyLight.svg deleted file mode 100644 index dee84de25..000000000 --- a/packages/web/components/common/Icon/icons/support/outlink/apikeyLight.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index f36a3ea8a..ad4f7efe6 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -82,6 +82,7 @@ "code_error.team_error.group_name_duplicate": "Duplicate group name", "code_error.team_error.group_name_empty": "Group name cannot be empty", "code_error.team_error.group_not_exist": "Group does not exist", + "code_error.team_error.not_user": "The member cannot be found", "code_error.team_error.org_member_duplicated": "Duplicate organization member", "code_error.team_error.org_member_not_exist": "Organization member does not exist", "code_error.team_error.org_not_exist": "Organization does not exist", diff --git a/packages/web/i18n/en/user.json b/packages/web/i18n/en/user.json index 3695f852d..091cffd3c 100644 --- a/packages/web/i18n/en/user.json +++ b/packages/web/i18n/en/user.json @@ -105,7 +105,7 @@ "team.group.role.admin": "administrator", "team.group.role.member": "member", "team.group.role.owner": "owner", - "team.group.search_placeholder": "Search member/group/org name", + "search_group_org_user": "Search member/group/org name", "team.group.set_as_admin": "Set as administrator", "team.group.toast.can_not_delete_owner": "Owner cannot be deleted, please transfer first", "team.group.transfer_owner": "transfer owner", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index 7aca2c892..770155ad8 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -86,6 +86,7 @@ "code_error.team_error.group_name_duplicate": "群组名称重复", "code_error.team_error.group_name_empty": "群组名称不能为空", "code_error.team_error.group_not_exist": "群组不存在", + "code_error.team_error.not_user": "找不到该成员", "code_error.team_error.org_member_duplicated": "重复的部门成员", "code_error.team_error.org_member_not_exist": "部门成员不存在", "code_error.team_error.org_not_exist": "部门不存在", diff --git a/packages/web/i18n/zh-CN/user.json b/packages/web/i18n/zh-CN/user.json index a8bf81d5a..e0ddec790 100644 --- a/packages/web/i18n/zh-CN/user.json +++ b/packages/web/i18n/zh-CN/user.json @@ -105,7 +105,7 @@ "team.group.role.admin": "管理员", "team.group.role.member": "成员", "team.group.role.owner": "所有者", - "team.group.search_placeholder": "搜索成员/部门/群组名称", + "search_group_org_user": "搜索成员/部门/群组名称", "team.group.set_as_admin": "设为管理员", "team.group.toast.can_not_delete_owner": "不能删除所有者, 请先转让", "team.group.transfer_owner": "转让所有者", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index dc3f4d736..70548bab2 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -82,6 +82,7 @@ "code_error.team_error.group_name_duplicate": "群組名稱重複", "code_error.team_error.group_name_empty": "群組名稱不能為空", "code_error.team_error.group_not_exist": "群組不存在", + "code_error.team_error.not_user": "找不到該成員", "code_error.team_error.org_member_duplicated": "重複的組織成員", "code_error.team_error.org_member_not_exist": "組織成員不存在", "code_error.team_error.org_not_exist": "組織不存在", diff --git a/packages/web/i18n/zh-Hant/user.json b/packages/web/i18n/zh-Hant/user.json index 35d58e31e..049178369 100644 --- a/packages/web/i18n/zh-Hant/user.json +++ b/packages/web/i18n/zh-Hant/user.json @@ -105,7 +105,7 @@ "team.group.role.admin": "管理員", "team.group.role.member": "成員", "team.group.role.owner": "擁有者", - "team.group.search_placeholder": "搜尋成員/部門/群組名稱", + "search_group_org_user": "搜尋成員/部門/群組名稱", "team.group.set_as_admin": "設為管理員", "team.group.toast.can_not_delete_owner": "無法刪除擁有者,請先轉移擁有權", "team.group.transfer_owner": "轉移擁有者", diff --git a/projects/app/public/imgs/modal/key.svg b/projects/app/public/imgs/modal/key.svg deleted file mode 100644 index 8b86419a3..000000000 --- a/projects/app/public/imgs/modal/key.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/projects/app/src/components/support/apikey/Table.tsx b/projects/app/src/components/support/apikey/Table.tsx index cc048d934..38e606375 100644 --- a/projects/app/src/components/support/apikey/Table.tsx +++ b/projects/app/src/components/support/apikey/Table.tsx @@ -250,7 +250,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => { {t('common:support.openapi.New api key')} @@ -330,7 +330,7 @@ function EditKeyModal({ return ( diff --git a/projects/app/src/components/support/permission/ConfigPerModal/index.tsx b/projects/app/src/components/support/permission/ConfigPerModal/index.tsx index e5cd606af..b2575f336 100644 --- a/projects/app/src/components/support/permission/ConfigPerModal/index.tsx +++ b/projects/app/src/components/support/permission/ConfigPerModal/index.tsx @@ -44,7 +44,7 @@ const ConfigPerModal = ({ <> diff --git a/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx b/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx index 6aa0731da..e51049b33 100644 --- a/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx +++ b/projects/app/src/components/support/permission/MemberManager/MemberModal.tsx @@ -22,7 +22,11 @@ import { useTranslation } from 'next-i18next'; import { useMemo, useRef, useState } from 'react'; import PermissionSelect from './PermissionSelect'; import PermissionTags from './PermissionTags'; -import { DEFAULT_ORG_AVATAR, DEFAULT_TEAM_AVATAR } from '@fastgpt/global/common/system/constants'; +import { + DEFAULT_ORG_AVATAR, + DEFAULT_TEAM_AVATAR, + DEFAULT_USER_AVATAR +} from '@fastgpt/global/common/system/constants'; import Path from '@/components/common/folder/Path'; import { getOrgChildrenPath } from '@fastgpt/global/support/user/team/org/constant'; import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type'; @@ -43,8 +47,7 @@ function MemberModal({ addPermissionOnly?: boolean; }) { const { t } = useTranslation(); - const { userInfo, loadAndGetTeamMembers, loadAndGetGroups, myGroups, loadAndGetOrgs } = - useUserStore(); + const { userInfo, loadAndGetTeamMembers, loadAndGetGroups, loadAndGetOrgs } = useUserStore(); const collaboratorList = useContextSelector(CollaboratorContext, (v) => v.collaboratorList); @@ -112,10 +115,11 @@ function MemberModal({ const filterMembers = useMemo(() => { if (searchText) return members.filter((item) => item.memberName.includes(searchText)); if (!searchText && filterClass !== 'member' && filterClass !== 'org') return []; - if (filterClass === 'org') { - if (!currentOrg) return []; + + if (currentOrg && filterClass === 'org') { return members.filter((item) => currentOrg.members.find((v) => v.tmbId === item.tmbId)); } + return members; }, [members, searchText, filterClass, currentOrg]); @@ -123,14 +127,15 @@ function MemberModal({ const filterGroups = useMemo(() => { if (searchText) return groups.filter((item) => item.name.includes(searchText)); if (!searchText && filterClass !== 'group') return []; - return groups.filter((item) => { - return !myGroups.find((i) => String(i._id) === String(item._id)); - }); - }, [groups, searchText, filterClass, myGroups]); + + return groups; + }, [groups, searchText, filterClass]); const permissionList = useContextSelector(CollaboratorContext, (v) => v.permissionList); const getPerLabelList = useContextSelector(CollaboratorContext, (v) => v.getPerLabelList); - const [selectedPermission, setSelectedPermission] = useState(); + const [selectedPermission, setSelectedPermission] = useState( + permissionList?.read?.value + ); const perLabel = useMemo(() => { if (selectedPermission === undefined) return ''; return getPerLabelList(selectedPermission!).join('、'); @@ -157,7 +162,7 @@ function MemberModal({ ); const entryList = useRef([ - { label: t('user:team.group.members'), icon: '/imgs/avatar/BlueAvatar.svg', value: 'member' }, + { label: t('user:team.group.members'), icon: DEFAULT_USER_AVATAR, value: 'member' }, { label: t('user:team.org.org'), icon: DEFAULT_ORG_AVATAR, value: 'org' }, { label: t('user:team.group.group'), icon: DEFAULT_TEAM_AVATAR, value: 'group' } ]); @@ -201,7 +206,7 @@ function MemberModal({ setSearchText(e.target.value)} /> @@ -364,11 +369,9 @@ function MemberModal({ {org.name} {org.count && ( - <> - - {org.count} - - + + {org.count} + )} { + if (userInfo?.permission.isOwner) return true; + if (userManage && !per.hasManagePer) return true; + return false; + }; return ( <> @@ -128,7 +132,7 @@ function PermissionManage({ {Tabs} {/* setSearchKey(e.target.value)} @@ -236,10 +240,9 @@ function PermissionManage({ /> - {userManage && - !member.permission.isOwner && - userInfo?.team.tmbId !== member.tmbId && ( - + + {hasDeletePer(member.permission) && + userInfo?.team.tmbId !== member.tmbId && ( - - )} + )} + ))} @@ -305,16 +308,16 @@ function PermissionManage({ /> - {userInfo?.permission.isOwner && ( - + + {hasDeletePer(org.permission) && ( onDeleteMemberPermission({ orgId: org.orgId! })} /> - - )} + )} + ))} @@ -385,16 +388,16 @@ function PermissionManage({ /> - {userInfo?.permission.isOwner && ( - + + {hasDeletePer(group.permission) && ( onDeleteMemberPermission({ groupId: group.groupId! })} /> - - )} + )} + ))} diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/AppCard.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/AppCard.tsx index 70b4f7969..37fa3337b 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/AppCard.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/AppCard.tsx @@ -66,7 +66,7 @@ const AppCard = ({ showSaveStatus, isSaved }: { showSaveStatus: boolean; isSaved cursor={'pointer'} onClick={onOpenInfoEdit} > - + {t('app:Role_setting')} diff --git a/projects/app/src/pages/app/list/components/List.tsx b/projects/app/src/pages/app/list/components/List.tsx index 85d1f070d..ff3144164 100644 --- a/projects/app/src/pages/app/list/components/List.tsx +++ b/projects/app/src/pages/app/list/components/List.tsx @@ -344,7 +344,7 @@ const ListItem = () => { ...(app.permission.hasManagePer ? [ { - icon: 'support/team/key', + icon: 'key', type: 'grayBg' as MenuItemType, label: t('common:permission.Permission'), onClick: () => setEditPerAppIndex(index) diff --git a/projects/app/src/pages/dataset/list/component/List.tsx b/projects/app/src/pages/dataset/list/component/List.tsx index 3300437d3..709990a99 100644 --- a/projects/app/src/pages/dataset/list/component/List.tsx +++ b/projects/app/src/pages/dataset/list/component/List.tsx @@ -350,7 +350,7 @@ function List() { ...(dataset.permission.hasManagePer ? [ { - icon: 'support/team/key', + icon: 'key', label: t('common:permission.Permission'), onClick: () => setEditPerDatasetIndex(index) }