From 8ad9e155718f8ade847b1bac015887877d09a187 Mon Sep 17 00:00:00 2001 From: heheer Date: Fri, 12 Dec 2025 16:08:20 +0800 Subject: [PATCH] free plan workorder entrance (#6085) --- packages/global/common/error/code/team.ts | 5 +++ packages/global/support/wallet/sub/type.d.ts | 1 + packages/web/i18n/en/common.json | 4 +++ packages/web/i18n/zh-CN/common.json | 3 ++ packages/web/i18n/zh-Hant/common.json | 4 +++ .../app/src/components/Layout/HelperBot.tsx | 30 +++++++++--------- .../wallet/NotSufficientModal/index.tsx | 3 +- .../wallet/StandardPlanContentList.tsx | 31 +++++++++++++------ .../src/web/common/system/useSystemStore.ts | 3 +- 9 files changed, 56 insertions(+), 28 deletions(-) diff --git a/packages/global/common/error/code/team.ts b/packages/global/common/error/code/team.ts index 4f8a891f9..0bb22442d 100644 --- a/packages/global/common/error/code/team.ts +++ b/packages/global/common/error/code/team.ts @@ -14,6 +14,7 @@ export enum TeamErrEnum { appFolderAmountNotEnough = 'appFolderAmountNotEnough', websiteSyncNotEnough = 'websiteSyncNotEnough', reRankNotEnough = 'reRankNotEnough', + ticketNotAvailable = 'ticketNotAvailable', groupNameEmpty = 'groupNameEmpty', groupNameDuplicate = 'groupNameDuplicate', groupNotExist = 'groupNotExist', @@ -78,6 +79,10 @@ const teamErr = [ statusText: TeamErrEnum.reRankNotEnough, message: i18nT('common:code_error.team_error.re_rank_not_enough') }, + { + statusText: TeamErrEnum.ticketNotAvailable, + message: i18nT('common:code_error.team_error.ticket_not_available') + }, { statusText: TeamErrEnum.groupNameEmpty, message: i18nT('common:code_error.team_error.group_name_empty') diff --git a/packages/global/support/wallet/sub/type.d.ts b/packages/global/support/wallet/sub/type.d.ts index cb8789f2e..54cc66fa9 100644 --- a/packages/global/support/wallet/sub/type.d.ts +++ b/packages/global/support/wallet/sub/type.d.ts @@ -43,6 +43,7 @@ export type SubPlanType = { [SubTypeEnum.standard]?: StandSubPlanLevelMapType; planDescriptionUrl?: string; appRegistrationUrl?: string; + communitySupportTip?: string; [SubTypeEnum.extraDatasetSize]: { price: number; }; diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index c68924495..f667ec17f 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -195,6 +195,7 @@ "code_error.team_error.over_size": "Team members exceed limit", "code_error.team_error.plugin_amount_not_enough": "Plugin Limit Reached", "code_error.team_error.re_rank_not_enough": "Search rearrangement cannot be used in the free version~", + "code_error.team_error.ticket_not_available": "The current package does not support work order services. You can go to the community to get help for free ~", "code_error.team_error.too_many_invitations": "You have reached the maximum number of active invitation links, please clean up some links first", "code_error.team_error.un_auth": "Unauthorized to Operate This Team", "code_error.team_error.user_not_active": "The user did not accept or has left the team", @@ -1224,6 +1225,9 @@ "support.wallet.subscription.function.Max members": "{{amount}} Member", "support.wallet.subscription.function.Points": "{{amount}} points", "support.wallet.subscription.function.Requests per minute": "{{amount}} QPM", + "support.wallet.subscription.function.Ticket response time": "{{amount}} hours ticket support response", + "support.wallet.subscription.function.Community free support": "Community free support", + "support.wallet.subscription.function.Community support tip": "Visit the FastGPT community for free help and technical support", "support.wallet.subscription.function.Website sync per dataset": "Single knowledge base {{amount}} web pages synchronized", "support.wallet.subscription.function.custom domain tip": "The number of custom domain names that the team can configure, which can currently be used to access Wecom intelligent robots", "support.wallet.subscription.mode.Month": "Month", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index c1c842e6e..9848851b6 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -196,6 +196,7 @@ "code_error.team_error.over_size": "团队成员超出限制", "code_error.team_error.plugin_amount_not_enough": "插件数量已达上限~", "code_error.team_error.re_rank_not_enough": "免费版无法使用检索重排~", + "code_error.team_error.ticket_not_available": "当前套餐暂不支持工单服务,可以前往社区免费获取帮助~", "code_error.team_error.too_many_invitations": "您的有效邀请链接数已达上限,请先清理链接", "code_error.team_error.un_auth": "无权操作该团队", "code_error.team_error.user_not_active": "用户未接受或已离开团队", @@ -1234,6 +1235,8 @@ "support.wallet.subscription.function.Points": "{{amount}} 积分", "support.wallet.subscription.function.Requests per minute": "{{amount}} QPM", "support.wallet.subscription.function.Ticket response time": "{{amount}} 小时工单支持响应", + "support.wallet.subscription.function.Community free support": "社区免费支持", + "support.wallet.subscription.function.Community support tip": "可前往 FastGPT 社区免费获取帮助和技术支持", "support.wallet.subscription.function.Website sync per dataset": "站点同步最大 {{amount}} 页", "support.wallet.subscription.function.custom domain tip": "团队可以配置的自定义域名数量,目前可用于接入企微智能机器人", "support.wallet.subscription.function.qpm tip": "主要指团队每分钟请求 Agent 的最大次数,与单个 Agent 复杂度无关。其他 OpenAPI 接口也受此影响,每个接口单独计算", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index f32a7a4a5..000f6bb4a 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -195,6 +195,7 @@ "code_error.team_error.over_size": "團隊成員超出限制", "code_error.team_error.plugin_amount_not_enough": "已達外掛程式數量上限", "code_error.team_error.re_rank_not_enough": "免費版無法使用檢索重排~", + "code_error.team_error.ticket_not_available": "當前套餐暫不支持工單服務,可以前往社區免費獲取幫助~", "code_error.team_error.too_many_invitations": "您的有效邀請連結數已達上限,請先清理連結", "code_error.team_error.un_auth": "無權操作此團隊", "code_error.team_error.user_not_active": "使用者未接受或已離開團隊", @@ -1221,6 +1222,9 @@ "support.wallet.subscription.function.Max members": "{{amount}} 個團隊成員", "support.wallet.subscription.function.Points": "{{amount}} 積分", "support.wallet.subscription.function.Requests per minute": "{{amount}} QPM", + "support.wallet.subscription.function.Ticket response time": "{{amount}} 小時工單支持響應", + "support.wallet.subscription.function.Community free support": "社群免費支持", + "support.wallet.subscription.function.Community support tip": "可前往 FastGPT 社群免費獲取幫助和技術支持", "support.wallet.subscription.function.Website sync per dataset": "單知識庫 {{amount}} 個網頁同步", "support.wallet.subscription.function.custom domain tip": "團隊可以配置的自定義域名數量,目前可用於接入企微智能機器人", "support.wallet.subscription.mode.Month": "按月", diff --git a/projects/app/src/components/Layout/HelperBot.tsx b/projects/app/src/components/Layout/HelperBot.tsx index 0ca32ab4c..96494a388 100644 --- a/projects/app/src/components/Layout/HelperBot.tsx +++ b/projects/app/src/components/Layout/HelperBot.tsx @@ -6,9 +6,9 @@ import { useRouter } from 'next/router'; import { useState, useEffect, useMemo } from 'react'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useUserStore } from '@/web/support/user/useUserStore'; -import { StandardSubLevelEnum } from '@fastgpt/global/support/wallet/sub/constants'; import { useTranslation } from 'next-i18next'; import { getWorkorderURL } from '@/web/common/workorder/api'; +import { TeamErrEnum } from '@fastgpt/global/common/error/code/team'; const BotShowRouter: { [key: string]: boolean } = { '/dashboard/agent': true, @@ -28,21 +28,14 @@ const HelperBot = () => { const [showChat, setShowChat] = useToggle(false); const [isLoading, setIsLoading] = useState(true); - const { feConfigs, subPlans } = useSystemStore(); + const { feConfigs, setNotSufficientModalType } = useSystemStore(); const { teamPlanStatus } = useUserStore(); - const isPlanUser = useMemo(() => { - if (!teamPlanStatus) return false; - if (teamPlanStatus.standard?.currentSubLevel !== StandardSubLevelEnum.free) return true; - if (teamPlanStatus.datasetMaxSize !== subPlans?.standard?.free?.maxDatasetSize) return true; - if (teamPlanStatus.totalPoints !== subPlans?.standard?.free?.totalPoints) return true; - return false; - }, [ - subPlans?.standard?.free?.maxDatasetSize, - subPlans?.standard?.free?.totalPoints, - teamPlanStatus - ]); - const showWorkorder = feConfigs?.show_workorder && isPlanUser; + const hasTicketAccess = useMemo(() => { + const ticketResponseTime = teamPlanStatus?.standard?.ticketResponseTime; + return ticketResponseTime !== undefined && ticketResponseTime > 0; + }, [teamPlanStatus?.standard?.ticketResponseTime]); + const botIframeUrl = feConfigs?.botIframeUrl; useEffect(() => { @@ -54,6 +47,11 @@ const HelperBot = () => { useEffect(() => { const handleMessage = async (event: MessageEvent) => { if (event.data?.type === 'workorderRequest') { + if (!hasTicketAccess) { + setNotSufficientModalType(TeamErrEnum.ticketNotAvailable); + return; + } + try { const data = await getWorkorderURL(); if (data?.redirectUrl) { @@ -67,7 +65,7 @@ const HelperBot = () => { window.addEventListener('message', handleMessage); return () => window.removeEventListener('message', handleMessage); - }, []); + }, [hasTicketAccess, setNotSufficientModalType]); if (!botIframeUrl || !BotShowRouter[router.pathname]) { return null; @@ -122,7 +120,7 @@ const HelperBot = () => { {/* iframe */} { [TeamErrEnum.appAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient'), [TeamErrEnum.pluginAmountNotEnough]: t('common:support.wallet.App_amount_not_sufficient'), [TeamErrEnum.websiteSyncNotEnough]: t('common:code_error.team_error.website_sync_not_enough'), - [TeamErrEnum.reRankNotEnough]: t('common:code_error.team_error.re_rank_not_enough') + [TeamErrEnum.reRankNotEnough]: t('common:code_error.team_error.re_rank_not_enough'), + [TeamErrEnum.ticketNotAvailable]: t('common:code_error.team_error.ticket_not_available') }; return type ? ( diff --git a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx index a79fd48b0..5faab0b77 100644 --- a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx +++ b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx @@ -9,6 +9,7 @@ import { useTranslation } from 'next-i18next'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import dynamic from 'next/dynamic'; import type { TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type'; +import Markdown from '@/components/Markdown'; const ModelPriceModal = dynamic(() => import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal) @@ -157,16 +158,26 @@ const StandardPlanContentList = ({ )} - {!!planContent.ticketResponseTime && ( - - - - {t('common:support.wallet.subscription.function.Ticket response time', { - amount: planContent.ticketResponseTime - })} - - - )} + + + + {planContent.ticketResponseTime + ? t('common:support.wallet.subscription.function.Ticket response time', { + amount: planContent.ticketResponseTime + }) + : t('common:support.wallet.subscription.function.Community free support')} + + {!planContent.ticketResponseTime && subPlans?.communitySupportTip && ( + + + + } + /> + )} + {!!planContent.appRegistrationCount && ( diff --git a/projects/app/src/web/common/system/useSystemStore.ts b/projects/app/src/web/common/system/useSystemStore.ts index 80ac350ab..5a56c33ad 100644 --- a/projects/app/src/web/common/system/useSystemStore.ts +++ b/projects/app/src/web/common/system/useSystemStore.ts @@ -29,7 +29,8 @@ export type NotSufficientModalType = | TeamErrEnum.aiPointsNotEnough | TeamErrEnum.datasetAmountNotEnough | TeamErrEnum.teamMemberOverSize - | TeamErrEnum.appAmountNotEnough; + | TeamErrEnum.appAmountNotEnough + | TeamErrEnum.ticketNotAvailable; type State = { initd: boolean;