diff --git a/.github/workflows/preview-admin-build.yml b/.github/workflows/preview-admin-build.yml index cb9c1d5006..9b92603e2e 100644 --- a/.github/workflows/preview-admin-build.yml +++ b/.github/workflows/preview-admin-build.yml @@ -25,7 +25,7 @@ permissions: jobs: build: - if: ${{ github.event.pull_request.author_association == 'MEMBER' }} + if: ${{ contains(fromJSON('["COLLABORATOR", "OWNER"]'), github.event.pull_request.author_association) }} runs-on: ubuntu-24.04 steps: diff --git a/.github/workflows/test-fastgpt-pro.yaml b/.github/workflows/test-fastgpt-pro.yaml index 7cca2b8ff5..caaef24f94 100644 --- a/.github/workflows/test-fastgpt-pro.yaml +++ b/.github/workflows/test-fastgpt-pro.yaml @@ -20,7 +20,7 @@ concurrency: jobs: test: - if: ${{ github.event_name != 'pull_request_target' || github.event.pull_request.author_association == 'MEMBER' }} + if: ${{ github.event_name != 'pull_request_target' || contains(fromJSON('["COLLABORATOR", "OWNER"]'), github.event.pull_request.author_association) }} runs-on: ubuntu-latest permissions: diff --git a/document/content/self-host/upgrading/4-15/4150.mdx b/document/content/self-host/upgrading/4-15/4150.mdx index 885250c97a..77506ba604 100644 --- a/document/content/self-host/upgrading/4-15/4150.mdx +++ b/document/content/self-host/upgrading/4-15/4150.mdx @@ -13,6 +13,8 @@ description: 'FastGPT V4.15.0 更新说明' 1. 增加父子节点选中互斥功能,解决:同时选中父子节点时,移动节点会出现抖动。 2. 调整文件注入 messages 位置,从 system 调整至 user,便于命中缓存。 +3. 非管理员/访客,触发余额不足时候,提示优化。 +4. 无创建权限时,隐藏模板功能。 ## 🐛 修复 diff --git a/document/data/doc-last-modified.json b/document/data/doc-last-modified.json index 3b9f9d8b14..33de75d4c0 100644 --- a/document/data/doc-last-modified.json +++ b/document/data/doc-last-modified.json @@ -231,6 +231,7 @@ "content/self-host/upgrading/4-14/41415.mdx": "2026-04-26T21:28:27+08:00", "content/self-host/upgrading/4-14/41416.en.mdx": "2026-04-26T21:28:27+08:00", "content/self-host/upgrading/4-14/41416.mdx": "2026-04-26T22:41:57+08:00", + "content/self-host/upgrading/4-14/41417.mdx": "2026-04-28T18:03:38+08:00", "content/self-host/upgrading/4-14/4142.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/4-14/4142.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/4-14/4143.en.mdx": "2026-04-26T21:08:47+08:00", @@ -251,7 +252,7 @@ "content/self-host/upgrading/4-14/41481.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/4-14/4149.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/4-14/4149.mdx": "2026-04-26T21:08:47+08:00", - "content/self-host/upgrading/4-15/4150.mdx": "2026-04-28T15:10:52+08:00", + "content/self-host/upgrading/4-15/4150.mdx": "2026-04-28T21:27:07+08:00", "content/self-host/upgrading/outdated/40.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/outdated/40.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/outdated/41.en.mdx": "2026-04-26T21:08:47+08:00", @@ -393,7 +394,7 @@ "content/self-host/upgrading/upgrade-intruction.en.mdx": "2026-04-26T21:08:47+08:00", "content/self-host/upgrading/upgrade-intruction.mdx": "2026-04-26T21:08:47+08:00", "content/toc.en.mdx": "2026-04-26T21:28:27+08:00", - "content/toc.mdx": "2026-04-26T21:28:27+08:00", + "content/toc.mdx": "2026-04-28T18:03:38+08:00", "content/use-cases/app-cases/dalle3.en.mdx": "2026-04-26T21:08:47+08:00", "content/use-cases/app-cases/dalle3.mdx": "2026-04-26T21:08:47+08:00", "content/use-cases/app-cases/english_essay_correction_bot.en.mdx": "2026-04-26T21:08:47+08:00", diff --git a/pro b/pro index 4aba60a784..70380fe539 160000 --- a/pro +++ b/pro @@ -1 +1 @@ -Subproject commit 4aba60a7842c0a4b952ba35daf93b68fd520ff81 +Subproject commit 70380fe53914fff72e256be0e3b4eb649ae1ad90 diff --git a/projects/app/src/pageComponents/dashboard/Container.tsx b/projects/app/src/pageComponents/dashboard/Container.tsx index 4bb81e6b16..46487c3589 100644 --- a/projects/app/src/pageComponents/dashboard/Container.tsx +++ b/projects/app/src/pageComponents/dashboard/Container.tsx @@ -1,7 +1,7 @@ import { Box, Divider, Flex, useDisclosure } from '@chakra-ui/react'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useTranslation } from 'next-i18next'; -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { AppTemplateTypeEnum, AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useRouter } from 'next/router'; @@ -36,11 +36,12 @@ const DashboardContainer = ({ }) => React.ReactNode; }) => { const router = useRouter(); - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const { isPc } = useSystem(); const { feConfigs } = useSystemStore(); const { isOpen: isOpenSidebar, onOpen: onOpenSidebar, onClose: onCloseSidebar } = useDisclosure(); const { userInfo } = useUserStore(); + const hasAppCreatePer = !!userInfo?.team.permission.hasAppCreatePer; // First tab const currentTab = useMemo(() => { @@ -56,10 +57,16 @@ const DashboardContainer = ({ appType?: AppTypeEnum | 'all'; }; + useEffect(() => { + if (userInfo && currentTab === TabEnum.app_templates && !hasAppCreatePer) { + router.replace('/dashboard/agent'); + } + }, [currentTab, hasAppCreatePer, router, userInfo]); + // Template market const { data: templateTags = [], loading: isLoadingTemplatesTags } = useRequest( () => - currentTab === TabEnum.app_templates + currentTab === TabEnum.app_templates && hasAppCreatePer ? getTemplateTagList().then((res) => [ { typeId: AppTemplateTypeEnum.recommendation, @@ -73,20 +80,20 @@ const DashboardContainer = ({ : Promise.resolve([]), { manual: false, - refreshDeps: [currentTab] + refreshDeps: [currentTab, hasAppCreatePer, userInfo?.team.isWecomTeam] } ); const { data: templateData, loading: isLoadingTemplates } = useRequest( () => - currentTab === TabEnum.app_templates + currentTab === TabEnum.app_templates && hasAppCreatePer ? getTemplateMarketItemList({ type: appType }) : Promise.resolve({ list: [], total: 0 }), { manual: false, - refreshDeps: [currentTab, appType] + refreshDeps: [currentTab, appType, hasAppCreatePer] } ); - const templateList = templateData?.list || []; + const templateList = useMemo(() => templateData?.list ?? [], [templateData?.list]); const groupList = useMemo< { @@ -167,40 +174,44 @@ const DashboardContainer = ({ groupName: t('common:system_tools'), children: [] }, - { - groupId: TabEnum.app_templates, - groupAvatar: 'common/templateMarket', - groupName: t('common:template_market'), - children: [ - ...templateTags - .map((tag) => { - const templates = templateList.filter((template) => - template.tags.includes(tag.typeId) - ); - return { - ...tag, - templates - }; - }) - .filter((tag) => tag.templates.length > 0) - .map((tag, index) => ({ - typeId: tag.typeId, - typeName: t(tag.typeName as any), - isActive: index === 0 && !currentType - })), - ...(feConfigs?.appTemplateCourse - ? [ - { - typeId: AppTemplateTypeEnum.contribute, - typeName: t('common:contribute_app_template'), - onClick: () => { - window.open(feConfigs.appTemplateCourse); - } - } + ...(hasAppCreatePer + ? [ + { + groupId: TabEnum.app_templates, + groupAvatar: 'common/templateMarket', + groupName: t('common:template_market'), + children: [ + ...templateTags + .map((tag) => { + const templates = templateList.filter((template) => + template.tags.includes(tag.typeId) + ); + return { + ...tag, + templates + }; + }) + .filter((tag) => tag.templates.length > 0) + .map((tag, index) => ({ + typeId: tag.typeId, + typeName: t(tag.typeName as any), + isActive: index === 0 && !currentType + })), + ...(feConfigs?.appTemplateCourse + ? [ + { + typeId: AppTemplateTypeEnum.contribute, + typeName: t('common:contribute_app_template'), + onClick: () => { + window.open(feConfigs.appTemplateCourse); + } + } + ] + : []) ] - : []) - ] - }, + } + ] + : []), { groupId: TabEnum.mcp_server, groupAvatar: 'mcp', @@ -223,6 +234,7 @@ const DashboardContainer = ({ feConfigs.appTemplateCourse, feConfigs?.isPlus, feConfigs?.show_skill, + hasAppCreatePer, t, templateList, templateTags diff --git a/projects/app/src/pages/dashboard/agent/index.tsx b/projects/app/src/pages/dashboard/agent/index.tsx index d4eb7712b5..7bfecbcc81 100644 --- a/projects/app/src/pages/dashboard/agent/index.tsx +++ b/projects/app/src/pages/dashboard/agent/index.tsx @@ -63,6 +63,10 @@ const MyApps = ({ MenuIcon }: { MenuIcon: JSX.Element }) => { onOpen: onOpenJsonImportModal, onClose: onCloseJsonImportModal } = useDisclosure(); + const hasCreatePer = folderDetail + ? folderDetail.permission.hasWritePer && folderDetail?.type !== AppTypeEnum.httpPlugin + : userInfo?.team.permission.hasAppCreatePer; + //if there is a workflow url in the session storage, open the json import modal and import the workflow useMount(() => { if (getUtmWorkflow()) { @@ -105,7 +109,7 @@ const MyApps = ({ MenuIcon }: { MenuIcon: JSX.Element }) => { overflowX={'hidden'} > {/* Only shown on pc root page */} - {!folderDetail && isPc && } + {!folderDetail && isPc && hasCreatePer && } {!isPc ? ( MenuIcon @@ -143,10 +147,7 @@ const MyApps = ({ MenuIcon }: { MenuIcon: JSX.Element }) => { /> )} - {(folderDetail - ? folderDetail.permission.hasWritePer && - folderDetail?.type !== AppTypeEnum.httpPlugin - : userInfo?.team.permission.hasAppCreatePer) && ( + {hasCreatePer && ( <>