mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-24 22:03:54 +00:00
feat: more sub plan info;fix: emprt index (#4997)
* feat: more sub plan info * fix: emprt index * doc
This commit is contained in:
@@ -112,7 +112,7 @@ const RechargeModal = ({
|
||||
<Box>{`${t('common:support.user.team.Dataset usage')}:`}</Box>
|
||||
<Box
|
||||
ml={2}
|
||||
>{`${teamPlanStatus?.usedDatasetSize} / ${teamPlanStatus?.datasetMaxSize || t('account_info:unlimited')}`}</Box>
|
||||
>{`${teamPlanStatus?.usedDatasetIndexSize} / ${teamPlanStatus?.datasetMaxSize || t('account_info:unlimited')}`}</Box>
|
||||
<Box ml={5}>{`${t('common:support.wallet.subscription.AI points usage')}:`}</Box>
|
||||
<Box
|
||||
ml={2}
|
||||
|
@@ -8,6 +8,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
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';
|
||||
|
||||
const ModelPriceModal = dynamic(() =>
|
||||
import('@/components/core/ai/ModelTable').then((mod) => mod.ModelPriceModal)
|
||||
@@ -15,10 +16,12 @@ const ModelPriceModal = dynamic(() =>
|
||||
|
||||
const StandardPlanContentList = ({
|
||||
level,
|
||||
mode
|
||||
mode,
|
||||
standplan
|
||||
}: {
|
||||
level: `${StandardSubLevelEnum}`;
|
||||
mode: `${SubModeEnum}`;
|
||||
standplan?: TeamSubSchema;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { subPlans } = useSystemStore();
|
||||
@@ -31,9 +34,9 @@ const StandardPlanContentList = ({
|
||||
price: plan.price * (mode === SubModeEnum.month ? 1 : 10),
|
||||
level: level as `${StandardSubLevelEnum}`,
|
||||
...standardSubLevelMap[level as `${StandardSubLevelEnum}`],
|
||||
maxTeamMember: plan.maxTeamMember,
|
||||
maxAppAmount: plan.maxAppAmount,
|
||||
maxDatasetAmount: plan.maxDatasetAmount,
|
||||
maxTeamMember: standplan?.maxTeamMember || plan.maxTeamMember,
|
||||
maxAppAmount: standplan?.maxApp || plan.maxAppAmount,
|
||||
maxDatasetAmount: standplan?.maxDataset || plan.maxDatasetAmount,
|
||||
chatHistoryStoreDuration: plan.chatHistoryStoreDuration,
|
||||
maxDatasetSize: plan.maxDatasetSize,
|
||||
permissionCustomApiKey: plan.permissionCustomApiKey,
|
||||
@@ -43,7 +46,14 @@ const StandardPlanContentList = ({
|
||||
permissionWebsiteSync: plan.permissionWebsiteSync,
|
||||
permissionTeamOperationLog: plan.permissionTeamOperationLog
|
||||
};
|
||||
}, [subPlans?.standard, level, mode]);
|
||||
}, [
|
||||
subPlans?.standard,
|
||||
level,
|
||||
mode,
|
||||
standplan?.maxTeamMember,
|
||||
standplan?.maxApp,
|
||||
standplan?.maxDataset
|
||||
]);
|
||||
|
||||
return planContent ? (
|
||||
<Grid gap={4} fontSize={'sm'} fontWeight={500}>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
'use client';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
@@ -70,10 +70,6 @@ const Info = () => {
|
||||
const standardPlan = teamPlanStatus?.standardConstants;
|
||||
const { isOpen: isOpenContact, onClose: onCloseContact, onOpen: onOpenContact } = useDisclosure();
|
||||
|
||||
useMount(() => {
|
||||
initUserInfo();
|
||||
});
|
||||
|
||||
return (
|
||||
<AccountContainer>
|
||||
<Box py={[3, '28px']} px={[5, 10]} mx={'auto'}>
|
||||
@@ -402,55 +398,77 @@ const PlanUsage = () => {
|
||||
}
|
||||
});
|
||||
|
||||
const datasetUsageMap = useMemo(() => {
|
||||
const valueColorSchema = useCallback((val: number) => {
|
||||
if (val < 50) return 'green';
|
||||
if (val < 80) return 'yellow';
|
||||
return 'red';
|
||||
}, []);
|
||||
|
||||
const datasetIndexUsageMap = useMemo(() => {
|
||||
if (!teamPlanStatus) {
|
||||
return {
|
||||
colorScheme: 'green',
|
||||
value: 0,
|
||||
maxSize: t('account_info:unlimited'),
|
||||
usedSize: 0
|
||||
max: t('account_info:unlimited'),
|
||||
rate: 0
|
||||
};
|
||||
}
|
||||
const rate = teamPlanStatus.usedDatasetSize / teamPlanStatus.datasetMaxSize;
|
||||
|
||||
const colorScheme = (() => {
|
||||
if (rate < 0.5) return 'green';
|
||||
if (rate < 0.8) return 'yellow';
|
||||
return 'red';
|
||||
})();
|
||||
const rate = teamPlanStatus.usedDatasetIndexSize / teamPlanStatus.datasetMaxSize;
|
||||
|
||||
return {
|
||||
colorScheme,
|
||||
value: rate * 100,
|
||||
maxSize: teamPlanStatus.datasetMaxSize || t('account_info:unlimited'),
|
||||
usedSize: teamPlanStatus.usedDatasetSize
|
||||
value: teamPlanStatus.usedDatasetIndexSize,
|
||||
rate: rate * 100,
|
||||
max: teamPlanStatus.datasetMaxSize || 1
|
||||
};
|
||||
}, [teamPlanStatus, t]);
|
||||
}, [t, teamPlanStatus]);
|
||||
const aiPointsUsageMap = useMemo(() => {
|
||||
if (!teamPlanStatus) {
|
||||
return {
|
||||
colorScheme: 'green',
|
||||
value: 0,
|
||||
maxSize: t('account_info:unlimited'),
|
||||
usedSize: 0
|
||||
max: t('account_info:unlimited'),
|
||||
rate: 0
|
||||
};
|
||||
}
|
||||
|
||||
const rate = teamPlanStatus.usedPoints / teamPlanStatus.totalPoints;
|
||||
|
||||
const colorScheme = (() => {
|
||||
if (rate < 0.5) return 'green';
|
||||
if (rate < 0.8) return 'yellow';
|
||||
return 'red';
|
||||
})();
|
||||
|
||||
return {
|
||||
colorScheme,
|
||||
value: rate * 100,
|
||||
max: teamPlanStatus.totalPoints ? teamPlanStatus.totalPoints : t('account_info:unlimited'),
|
||||
used: teamPlanStatus.usedPoints ? Math.round(teamPlanStatus.usedPoints) : 0
|
||||
value: Math.round(teamPlanStatus.usedPoints),
|
||||
max: teamPlanStatus.totalPoints,
|
||||
rate: (teamPlanStatus.usedPoints / teamPlanStatus.totalPoints) * 100
|
||||
};
|
||||
}, [teamPlanStatus, t]);
|
||||
}, [t, teamPlanStatus]);
|
||||
|
||||
const limitData = useMemo(() => {
|
||||
if (!teamPlanStatus) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: t('account_info:member_amount'),
|
||||
value: teamPlanStatus.usedMember,
|
||||
max: teamPlanStatus?.standardConstants?.maxTeamMember || t('account_info:unlimited'),
|
||||
rate:
|
||||
(teamPlanStatus.usedMember / (teamPlanStatus?.standardConstants?.maxTeamMember || 1)) *
|
||||
100
|
||||
},
|
||||
{
|
||||
label: t('account_info:app_amount'),
|
||||
value: teamPlanStatus.usedAppAmount,
|
||||
max: teamPlanStatus?.standardConstants?.maxAppAmount || t('account_info:unlimited'),
|
||||
rate:
|
||||
(teamPlanStatus.usedAppAmount / (teamPlanStatus?.standardConstants?.maxAppAmount || 1)) *
|
||||
100
|
||||
},
|
||||
{
|
||||
label: t('account_info:dataset_amount'),
|
||||
value: teamPlanStatus.usedDatasetSize,
|
||||
max: teamPlanStatus?.standardConstants?.maxDatasetAmount || t('account_info:unlimited'),
|
||||
rate:
|
||||
(teamPlanStatus.usedDatasetSize /
|
||||
(teamPlanStatus?.standardConstants?.maxDatasetAmount || 1)) *
|
||||
100
|
||||
}
|
||||
];
|
||||
}, [t, teamPlanStatus]);
|
||||
|
||||
return standardPlan ? (
|
||||
<Box mt={[6, 0]}>
|
||||
@@ -531,6 +549,7 @@ const PlanUsage = () => {
|
||||
<StandardPlanContentList
|
||||
level={standardPlan?.currentSubLevel}
|
||||
mode={standardPlan.currentMode}
|
||||
standplan={standardPlan}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -574,15 +593,15 @@ const PlanUsage = () => {
|
||||
{t('account_info:knowledge_base_capacity')}
|
||||
</Box>
|
||||
<Box color={'myGray.600'} ml={2}>
|
||||
{datasetUsageMap.usedSize}/{datasetUsageMap.maxSize}
|
||||
{datasetIndexUsageMap.value}/{datasetIndexUsageMap.max}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Box mt={3}>
|
||||
<Box mt={1}>
|
||||
<Progress
|
||||
size={'sm'}
|
||||
value={datasetUsageMap.value}
|
||||
colorScheme={datasetUsageMap.colorScheme}
|
||||
value={datasetIndexUsageMap.rate}
|
||||
colorScheme={valueColorSchema(datasetIndexUsageMap.rate)}
|
||||
borderRadius={'md'}
|
||||
isAnimated
|
||||
hasStripe
|
||||
@@ -591,7 +610,7 @@ const PlanUsage = () => {
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box mt="9" width={'100%'} fontSize={'sm'}>
|
||||
<Box mt="6" width={'100%'} fontSize={'sm'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box fontWeight={'bold'} color={'myGray.900'}>
|
||||
@@ -599,15 +618,15 @@ const PlanUsage = () => {
|
||||
</Box>
|
||||
<QuestionTip ml={1} label={t('account_info:ai_points_usage_tip')}></QuestionTip>
|
||||
<Box color={'myGray.600'} ml={2}>
|
||||
{aiPointsUsageMap.used}/{aiPointsUsageMap.max}
|
||||
{aiPointsUsageMap.value}/{aiPointsUsageMap.max}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Box mt={3}>
|
||||
<Box mt={1}>
|
||||
<Progress
|
||||
size={'sm'}
|
||||
value={aiPointsUsageMap.value}
|
||||
colorScheme={aiPointsUsageMap.colorScheme}
|
||||
value={aiPointsUsageMap.rate}
|
||||
colorScheme={valueColorSchema(aiPointsUsageMap.rate)}
|
||||
borderRadius={'md'}
|
||||
isAnimated
|
||||
hasStripe
|
||||
@@ -616,6 +635,42 @@ const PlanUsage = () => {
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<MyDivider />
|
||||
|
||||
{limitData.map((item) => {
|
||||
return (
|
||||
<Box
|
||||
key={item.label}
|
||||
_notFirst={{
|
||||
mt: 4
|
||||
}}
|
||||
width={'100%'}
|
||||
fontSize={'sm'}
|
||||
>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box fontWeight={'bold'} color={'myGray.900'}>
|
||||
{item.label}
|
||||
</Box>
|
||||
<Box color={'myGray.600'} ml={2}>
|
||||
{item.value}/{item.max}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Box mt={1}>
|
||||
<Progress
|
||||
size={'sm'}
|
||||
value={item.rate}
|
||||
colorScheme={valueColorSchema(item.rate)}
|
||||
borderRadius={'md'}
|
||||
isAnimated
|
||||
hasStripe
|
||||
borderWidth={'1px'}
|
||||
borderColor={'borderColor.low'}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
{isOpenStandardModal && <StandDetailModal onClose={onCloseStandardModal} />}
|
||||
{isOpenRedeemCouponModal && (
|
||||
|
@@ -12,7 +12,7 @@ import { getCollectionWithDataset } from '@fastgpt/service/core/dataset/controll
|
||||
import { pushGenerateVectorUsage } from '@/service/support/wallet/usage/push';
|
||||
import type { InsertOneDatasetDataProps } from '@/global/core/dataset/api';
|
||||
import { simpleText } from '@fastgpt/global/common/string/tools';
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { checkDatasetIndexLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
@@ -41,9 +41,9 @@ async function handler(req: NextApiRequest) {
|
||||
per: WritePermissionVal
|
||||
});
|
||||
|
||||
await checkDatasetLimit({
|
||||
await checkDatasetIndexLimit({
|
||||
teamId,
|
||||
insertLen: 1
|
||||
insertLen: 1 + (indexes?.length || 0)
|
||||
});
|
||||
|
||||
const [
|
||||
|
@@ -2,7 +2,7 @@
|
||||
import type { NextApiResponse } from 'next';
|
||||
import type { PushDatasetDataProps } from '@fastgpt/global/core/dataset/api.d';
|
||||
import { authDatasetCollection } from '@fastgpt/service/support/permission/dataset/auth';
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { checkDatasetIndexLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { predictDataLimitLength } from '@fastgpt/global/core/dataset/utils';
|
||||
import { pushDataListToTrainingQueue } from '@fastgpt/service/core/dataset/training/controller';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
@@ -35,7 +35,7 @@ async function handler(req: ApiRequestProps<PushDatasetDataProps>, res: NextApiR
|
||||
});
|
||||
|
||||
// auth dataset limit
|
||||
await checkDatasetLimit({
|
||||
await checkDatasetIndexLimit({
|
||||
teamId,
|
||||
insertLen: predictDataLimitLength(getTrainingModeByCollection(collection), data)
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { checkDatasetIndexLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -19,7 +19,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
|
||||
const numberSize = Number(size);
|
||||
|
||||
await checkDatasetLimit({
|
||||
await checkDatasetIndexLimit({
|
||||
teamId,
|
||||
insertLen: numberSize
|
||||
});
|
||||
|
@@ -2,17 +2,53 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { getTeamPlanStatus } from '@fastgpt/service/support/wallet/sub/utils';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import type { ClientTeamPlanStatusType } from '@fastgpt/global/support/wallet/sub/type';
|
||||
import { MongoApp } from '@fastgpt/service/core/app/schema';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { getVectorCountByTeamId } from '@fastgpt/service/common/vectorDB/controller';
|
||||
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
|
||||
import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<any>
|
||||
): Promise<ClientTeamPlanStatusType | undefined> {
|
||||
try {
|
||||
const { teamId } = await authCert({
|
||||
req,
|
||||
authToken: true
|
||||
});
|
||||
|
||||
return getTeamPlanStatus({
|
||||
teamId
|
||||
});
|
||||
const [planStatus, usedMember, usedAppAmount, usedDatasetSize, usedDatasetIndexSize] =
|
||||
await Promise.all([
|
||||
getTeamPlanStatus({
|
||||
teamId
|
||||
}),
|
||||
MongoTeamMember.countDocuments({
|
||||
teamId,
|
||||
status: { $ne: TeamMemberStatusEnum.leave }
|
||||
}),
|
||||
MongoApp.countDocuments({
|
||||
teamId,
|
||||
type: {
|
||||
$in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.tool]
|
||||
}
|
||||
}),
|
||||
MongoDataset.countDocuments({
|
||||
type: { $ne: DatasetTypeEnum.folder }
|
||||
}),
|
||||
getVectorCountByTeamId(teamId)
|
||||
]);
|
||||
|
||||
return {
|
||||
...planStatus,
|
||||
usedMember,
|
||||
usedAppAmount,
|
||||
usedDatasetSize,
|
||||
usedDatasetIndexSize
|
||||
};
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
|
@@ -73,13 +73,11 @@ const formatIndexes = async ({
|
||||
};
|
||||
|
||||
// If index not type, set it to custom
|
||||
indexes = indexes
|
||||
.map((item) => ({
|
||||
text: typeof item.text === 'string' ? item.text : String(item.text),
|
||||
type: item.type || DatasetDataIndexTypeEnum.custom,
|
||||
dataId: item.dataId
|
||||
}))
|
||||
.filter((item) => !!item.text.trim());
|
||||
indexes = indexes.map((item) => ({
|
||||
text: typeof item.text === 'string' ? item.text : String(item.text),
|
||||
type: item.type || DatasetDataIndexTypeEnum.custom,
|
||||
dataId: item.dataId
|
||||
}));
|
||||
|
||||
// Recompute default indexes, Merge ids of the same index, reduce the number of rebuilds
|
||||
const defaultIndexes = await getDefaultIndex({ q, a, indexSize });
|
||||
@@ -134,7 +132,7 @@ const formatIndexes = async ({
|
||||
)
|
||||
).flat();
|
||||
|
||||
return chekcIndexes;
|
||||
return chekcIndexes.filter((item) => !!item.text.trim());
|
||||
};
|
||||
/* insert data.
|
||||
* 1. create data id
|
||||
|
@@ -20,7 +20,7 @@ import { delay } from '@fastgpt/service/common/bullmq';
|
||||
import { rawText2Chunks, readDatasetSourceRawText } from '@fastgpt/service/core/dataset/read';
|
||||
import { getLLMModel } from '@fastgpt/service/core/ai/model';
|
||||
import { getLLMMaxChunkSize } from '@fastgpt/global/core/dataset/training/utils';
|
||||
import { checkDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { checkDatasetIndexLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { predictDataLimitLength } from '@fastgpt/global/core/dataset/utils';
|
||||
import { getTrainingModeByCollection } from '@fastgpt/service/core/dataset/collection/utils';
|
||||
import { pushDataListToTrainingQueue } from '@fastgpt/service/core/dataset/training/controller';
|
||||
@@ -258,7 +258,7 @@ export const datasetParseQueue = async (): Promise<any> => {
|
||||
|
||||
// Check dataset limit
|
||||
try {
|
||||
await checkDatasetLimit({
|
||||
await checkDatasetIndexLimit({
|
||||
teamId: data.teamId,
|
||||
insertLen: predictDataLimitLength(trainingMode, chunks)
|
||||
});
|
||||
|
@@ -15,7 +15,10 @@ import type {
|
||||
TeamMemberItemType,
|
||||
TeamMemberSchema
|
||||
} from '@fastgpt/global/support/user/team/type.d';
|
||||
import type { FeTeamPlanStatusType, TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type';
|
||||
import type {
|
||||
ClientTeamPlanStatusType,
|
||||
TeamSubSchema
|
||||
} from '@fastgpt/global/support/wallet/sub/type';
|
||||
import type { TeamInvoiceHeaderType } from '@fastgpt/global/support/user/team/type';
|
||||
import type { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
import type {
|
||||
@@ -100,7 +103,7 @@ export const checkTeamDatasetSizeLimit = (size: number) =>
|
||||
|
||||
/* plans */
|
||||
export const getTeamPlanStatus = () =>
|
||||
GET<FeTeamPlanStatusType>(`/support/user/team/plan/getTeamPlanStatus`, { maxQuantity: 1 });
|
||||
GET<ClientTeamPlanStatusType>(`/support/user/team/plan/getTeamPlanStatus`, { maxQuantity: 1 });
|
||||
export const getTeamPlans = () =>
|
||||
GET<TeamSubSchema[]>(`/proApi/support/user/team/plan/getTeamPlans`);
|
||||
|
||||
|
@@ -1,13 +1,11 @@
|
||||
import { create, devtools, persist, immer } from '@fastgpt/web/common/zustand';
|
||||
|
||||
import type { UserUpdateParams } from '@/types/user';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { getTokenLogin, putUserInfo } from '@/web/support/user/api';
|
||||
import type { OrgType } from '@fastgpt/global/support/user/team/org/type';
|
||||
import type { UserType } from '@fastgpt/global/support/user/type.d';
|
||||
import type { FeTeamPlanStatusType } from '@fastgpt/global/support/wallet/sub/type';
|
||||
import type { ClientTeamPlanStatusType } from '@fastgpt/global/support/wallet/sub/type';
|
||||
import { getTeamPlanStatus } from './team/api';
|
||||
import { getGroupList } from './team/group/api';
|
||||
|
||||
type State = {
|
||||
systemMsgReadId: string;
|
||||
@@ -22,7 +20,7 @@ type State = {
|
||||
setUserInfo: (user: UserType | null) => void;
|
||||
updateUserInfo: (user: UserUpdateParams) => Promise<void>;
|
||||
|
||||
teamPlanStatus: FeTeamPlanStatusType | null;
|
||||
teamPlanStatus: ClientTeamPlanStatusType | null;
|
||||
initTeamPlanStatus: () => Promise<any>;
|
||||
|
||||
teamOrgs: OrgType[];
|
||||
|
Reference in New Issue
Block a user