diff --git a/packages/global/openapi/support/wallet/bill/api.ts b/packages/global/openapi/support/wallet/bill/api.ts index 3e746eecb..781d339ee 100644 --- a/packages/global/openapi/support/wallet/bill/api.ts +++ b/packages/global/openapi/support/wallet/bill/api.ts @@ -25,6 +25,32 @@ export const BillListResponseSchema = z.object({ }); export type GetBillListResponseType = z.infer; +// Bill detail +export const BillDetailQuerySchema = z.object({ + billId: ObjectIdSchema.meta({ description: '订单 ID' }) +}); +export type BillDetailQueryType = z.infer; +export const BillDetailResponseSchema = BillSchema.safeExtend({ + discountCouponName: z.string().optional(), + couponDetail: z + .object({ + key: z.string(), + type: z.enum(CouponTypeEnum), + subscriptions: z.array( + z.object({ + type: z.enum(SubTypeEnum), + durationDay: z.number(), + totalPoints: z.number().optional(), + level: z.enum(StandardSubLevelEnum).optional(), + extraDatasetSize: z.number().optional(), + customConfig: z.record(z.string(), z.any()).optional() + }) + ) + }) + .optional() +}); +export type BillDetailResponseType = z.infer; + // Create export const CreateStandPlanBillSchema = z .object({ @@ -88,30 +114,14 @@ export const CheckPayResultResponseSchema = z.object({ }); export type CheckPayResultResponseType = z.infer; -// Bill detail -export const BillDetailResponseSchema = BillSchema.safeExtend({ - discountCouponName: z.string().optional(), - couponDetail: z - .object({ - key: z.string(), - type: z.enum(CouponTypeEnum), - subscriptions: z.array( - z.object({ - type: z.enum(SubTypeEnum), - durationDay: z.number(), - totalPoints: z.number().optional(), - level: z.enum(StandardSubLevelEnum).optional(), - extraDatasetSize: z.number().optional(), - customConfig: z.record(z.string(), z.any()).optional() - }) - ) - }) - .optional() -}); -export type BillDetailResponseType = z.infer; - // Cancel bill export const CancelBillPropsSchema = z.object({ billId: ObjectIdSchema.meta({ description: '订单 ID' }) }); export type CancelBillPropsType = z.infer; + +// Check pay result +export const CheckPayResultQuerySchema = z.object({ + payId: ObjectIdSchema.meta({ description: '订单 ID' }) +}); +export type CheckPayResultQueryType = z.infer; diff --git a/packages/global/openapi/support/wallet/bill/index.ts b/packages/global/openapi/support/wallet/bill/index.ts index 9356dc811..2a738f2f4 100644 --- a/packages/global/openapi/support/wallet/bill/index.ts +++ b/packages/global/openapi/support/wallet/bill/index.ts @@ -8,7 +8,9 @@ import { CheckPayResultResponseSchema, BillDetailResponseSchema, BillListQuerySchema, - CancelBillPropsSchema + CancelBillPropsSchema, + CheckPayResultQuerySchema, + BillDetailQuerySchema } from './api'; import { TagsMap } from '../../../tag'; import { ObjectIdSchema } from '../../../../common/type/mongo'; @@ -68,11 +70,7 @@ export const BillPath: OpenAPIPath = { description: '检查订单的支付状态,用于轮询支付结果', tags: [TagsMap.walletBill], requestParams: { - query: z.object({ - payId: ObjectIdSchema.meta({ - description: '订单 ID' - }) - }) + query: CheckPayResultQuerySchema }, responses: { 200: { @@ -92,11 +90,7 @@ export const BillPath: OpenAPIPath = { description: '根据订单 ID 获取订单详细信息,包括优惠券名称等', tags: [TagsMap.walletBill], requestParams: { - query: z.object({ - billId: ObjectIdSchema.meta({ - description: '订单 ID' - }) - }) + query: BillDetailQuerySchema }, responses: { 200: { diff --git a/packages/global/support/wallet/sub/api.d.ts b/packages/global/support/wallet/sub/api.d.ts index 9d716567c..feac8c9ca 100644 --- a/packages/global/support/wallet/sub/api.d.ts +++ b/packages/global/support/wallet/sub/api.d.ts @@ -1,5 +1,4 @@ import type { StandardSubLevelEnum, SubModeEnum } from './constants'; -import { TeamSubSchema } from './type.d'; export type StandardSubPlanParams = { level: `${StandardSubLevelEnum}`; diff --git a/packages/global/support/wallet/sub/type.d.ts b/packages/global/support/wallet/sub/type.d.ts deleted file mode 100644 index 7e81df96b..000000000 --- a/packages/global/support/wallet/sub/type.d.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { StandardSubLevelEnum, SubModeEnum, SubTypeEnum } from './constants'; - -// Content of plan -export type TeamStandardSubPlanItemType = { - name?: string; - desc?: string; // Plan description - price: number; // read price / month - - pointPrice: number; // read price/ one thousand - - totalPoints: number; // n - maxTeamMember: number; - maxAppAmount: number; // max app or plugin amount - maxDatasetAmount: number; - maxDatasetSize: number; - - requestsPerMinute?: number; - appRegistrationCount?: number; - chatHistoryStoreDuration: number; // n day - websiteSyncPerDataset?: number; - auditLogStoreDuration?: number; - ticketResponseTime?: number; - customDomain?: number; - - // Activity promotion fields - annualBonusPoints?: number; - - // Custom plan specific fields - priceDescription?: string; - customFormUrl?: string; - customDescriptions?: string[]; -}; - -export type StandSubPlanLevelMapType = Record< - `${StandardSubLevelEnum}`, - TeamStandardSubPlanItemType ->; - -export type PointsPackageItem = { - points: number; - month: number; - price: number; - activityBonusPoints?: number; -}; - -export type SubPlanType = { - [SubTypeEnum.standard]?: StandSubPlanLevelMapType; - planDescriptionUrl?: string; - appRegistrationUrl?: string; - communitySupportTip?: string; - activityExpirationTime?: string; - [SubTypeEnum.extraDatasetSize]: { - price: number; - }; - [SubTypeEnum.extraPoints]: { - packages: PointsPackageItem[]; - }; -}; - -export type TeamSubSchema = { - _id: string; - teamId: string; - type: `${SubTypeEnum}`; - startTime: Date; - expiredTime: Date; - - currentMode: `${SubModeEnum}`; - nextMode: `${SubModeEnum}`; - currentSubLevel: StandardSubLevelEnum; - nextSubLevel: StandardSubLevelEnum; - maxTeamMember?: number; - maxApp?: number; - maxDataset?: number; - - // custom level configurations - requestsPerMinute?: number; - chatHistoryStoreDuration?: number; - maxDatasetSize?: number; - websiteSyncPerDataset?: number; - appRegistrationCount?: number; - auditLogStoreDuration?: number; - ticketResponseTime?: number; - customDomain?: number; - - // Activity promotion fields - annualBonusPoints?: number; - - totalPoints: number; - surplusPoints: number; - - currentExtraDatasetSize: number; -}; - -export type TeamPlanStatusType = { - [SubTypeEnum.standard]?: TeamSubSchema; - standardConstants?: TeamStandardSubPlanItemType; - - totalPoints: number; - usedPoints: number; - - // standard + extra - datasetMaxSize: number; -}; - -export type ClientTeamPlanStatusType = TeamPlanStatusType & { - usedMember: number; - usedAppAmount: number; - usedDatasetSize: number; - usedDatasetIndexSize: number; - usedRegistrationCount: number; -}; diff --git a/packages/global/support/wallet/sub/type.ts b/packages/global/support/wallet/sub/type.ts new file mode 100644 index 000000000..1e2d47343 --- /dev/null +++ b/packages/global/support/wallet/sub/type.ts @@ -0,0 +1,111 @@ +import z from 'zod'; +import { StandardSubLevelEnum, SubModeEnum, SubTypeEnum } from './constants'; +import { ObjectIdSchema } from '../../../common/type/mongo'; + +// Content of plan +export const TeamStandardSubPlanItemSchema = z.object({ + name: z.string().optional(), + desc: z.string().optional(), + price: z.number(), + + totalPoints: z.int(), // 总积分 + maxTeamMember: z.int(), + maxAppAmount: z.int(), + maxDatasetAmount: z.int(), + maxDatasetSize: z.int(), + + requestsPerMinute: z.int().optional(), // QPM + appRegistrationCount: z.int().optional(), // 应用备案数量 + chatHistoryStoreDuration: z.int(), // 历史记录保留天数 + websiteSyncPerDataset: z.int().optional(), // 站点同步最大页面 + auditLogStoreDuration: z.int().optional(), // 审计日志保留天数 + ticketResponseTime: z.int().optional(), // 工单支持时间 + customDomain: z.int().optional(), // 自定义域名数量 + + // 定制套餐 + priceDescription: z.string().optional(), // 价格描述 + customFormUrl: z.string().optional(), // 自定义表单 URL + customDescriptions: z.array(z.string()).optional(), // 自定义描述 + + // Active + annualBonusPoints: z.int().optional(), // 年度赠送积分 + + // @deprecated + pointPrice: z.number().optional() +}); +export type TeamStandardSubPlanItemType = z.infer; + +export const StandSubPlanLevelMapSchema = z.record( + z.enum(StandardSubLevelEnum), + TeamStandardSubPlanItemSchema +); +export type StandSubPlanLevelMapType = z.infer; + +export const PointsPackageItemSchema = z.object({ + points: z.int(), + month: z.int(), + price: z.number(), + activityBonusPoints: z.int().optional() // 活动赠送积分 +}); +export type PointsPackageItem = z.infer; + +export const SubPlanSchema = z.object({ + [SubTypeEnum.standard]: StandSubPlanLevelMapSchema.optional(), + [SubTypeEnum.extraDatasetSize]: z.object({ price: z.number() }).optional(), + [SubTypeEnum.extraPoints]: z.object({ packages: PointsPackageItemSchema.array() }).optional(), + planDescriptionUrl: z.string().optional(), + appRegistrationUrl: z.string().optional(), + communitySupportTip: z.string().optional(), + activityExpirationTime: z.date().optional() +}); +export type SubPlanType = z.infer; + +export const TeamSubSchema = z.object({ + _id: ObjectIdSchema, + teamId: ObjectIdSchema, + type: z.enum(SubTypeEnum), + startTime: z.date(), + expiredTime: z.date(), + + currentMode: z.enum(SubModeEnum), + nextMode: z.enum(SubModeEnum), + currentSubLevel: z.enum(StandardSubLevelEnum), + nextSubLevel: z.enum(StandardSubLevelEnum), + + maxTeamMember: z.int().optional(), + maxApp: z.int().optional(), + maxDataset: z.int().optional(), + totalPoints: z.int(), + annualBonusPoints: z.int().optional(), + surplusPoints: z.int(), + currentExtraDatasetSize: z.int(), + + // 定制版特有属性 + requestsPerMinute: z.int().optional(), + chatHistoryStoreDuration: z.int().optional(), + maxDatasetSize: z.int().optional(), + websiteSyncPerDataset: z.int().optional(), + appRegistrationCount: z.int().optional(), + auditLogStoreDuration: z.int().optional(), + ticketResponseTime: z.int().optional(), + customDomain: z.int().optional() +}); +export type TeamSubSchemaType = z.infer; + +export const TeamPlanStatusSchema = z.object({ + [SubTypeEnum.standard]: TeamSubSchema.optional(), + standardConstants: TeamStandardSubPlanItemSchema.optional(), + totalPoints: z.int(), + usedPoints: z.int(), + datasetMaxSize: z.int() +}); +export type TeamPlanStatusType = z.infer; + +export const ClientTeamPlanStatusSchema = TeamPlanStatusSchema.extend({ + usedMember: z.int(), + usedAppAmount: z.int(), + usedDatasetSize: z.int(), + usedDatasetIndexSize: z.int(), + usedRegistrationCount: z.int() +}); +export type ClientTeamPlanStatusType = z.infer; diff --git a/packages/service/support/wallet/sub/schema.ts b/packages/service/support/wallet/sub/schema.ts index 93532bd7d..8b934124c 100644 --- a/packages/service/support/wallet/sub/schema.ts +++ b/packages/service/support/wallet/sub/schema.ts @@ -11,7 +11,7 @@ import { SubModeEnum, SubTypeEnum } from '@fastgpt/global/support/wallet/sub/constants'; -import type { TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type'; +import type { TeamSubSchemaType } from '@fastgpt/global/support/wallet/sub/type'; export const subCollectionName = 'team_subscriptions'; @@ -100,4 +100,4 @@ try { console.log(error); } -export const MongoTeamSub = getMongoModel(subCollectionName, SubSchema); +export const MongoTeamSub = getMongoModel(subCollectionName, SubSchema); diff --git a/packages/service/support/wallet/sub/utils.ts b/packages/service/support/wallet/sub/utils.ts index 2388b608b..941213505 100644 --- a/packages/service/support/wallet/sub/utils.ts +++ b/packages/service/support/wallet/sub/utils.ts @@ -7,8 +7,8 @@ import { import { MongoTeamSub } from './schema'; import { type TeamPlanStatusType, - type TeamSubSchema -} from '@fastgpt/global/support/wallet/sub/type.d'; + type TeamSubSchemaType +} from '@fastgpt/global/support/wallet/sub/type'; import dayjs from 'dayjs'; import { type ClientSession } from '../../../common/mongo'; import { addMonths } from 'date-fns'; @@ -29,7 +29,7 @@ export const getStandardPlanConfig = (level: `${StandardSubLevelEnum}`) => { return global.subPlans?.standard?.[level]; }; -export const sortStandPlans = (plans: TeamSubSchema[]) => { +export const sortStandPlans = (plans: TeamSubSchemaType[]) => { return plans.sort( (a, b) => standardSubLevelMap[b.currentSubLevel].weight - standardSubLevelMap[a.currentSubLevel].weight diff --git a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx index d0bc0a1d4..3827e20e8 100644 --- a/projects/app/src/components/support/wallet/StandardPlanContentList.tsx +++ b/projects/app/src/components/support/wallet/StandardPlanContentList.tsx @@ -8,7 +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'; +import type { TeamSubSchemaType } from '@fastgpt/global/support/wallet/sub/type'; import Markdown from '@/components/Markdown'; import MyPopover from '@fastgpt/web/components/common/MyPopover'; @@ -23,7 +23,7 @@ const StandardPlanContentList = ({ }: { level: `${StandardSubLevelEnum}`; mode: `${SubModeEnum}`; - standplan?: TeamSubSchema; + standplan?: TeamSubSchemaType; }) => { const { t } = useTranslation(); const { subPlans } = useSystemStore(); diff --git a/projects/app/src/pageComponents/price/Standard.tsx b/projects/app/src/pageComponents/price/Standard.tsx index 76d6e641a..c32d73056 100644 --- a/projects/app/src/pageComponents/price/Standard.tsx +++ b/projects/app/src/pageComponents/price/Standard.tsx @@ -6,7 +6,7 @@ import { StandardSubLevelEnum, SubModeEnum } from '@fastgpt/global/support/walle import { useSystemStore } from '@/web/common/system/useSystemStore'; import { standardSubLevelMap } from '@fastgpt/global/support/wallet/sub/constants'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; -import { type TeamSubSchema } from '@fastgpt/global/support/wallet/sub/type'; +import { type TeamSubSchemaType } from '@fastgpt/global/support/wallet/sub/type'; import QRCodePayModal, { type QRPayProps } from '@/components/support/wallet/QRCodePayModal'; import { postCreatePayBill } from '@/web/support/wallet/bill/api'; import { getDiscountCouponList } from '@/web/support/wallet/sub/discountCoupon/api'; @@ -28,7 +28,7 @@ const Standard = ({ standardPlan: myStandardPlan, onPaySuccess }: { - standardPlan?: TeamSubSchema; + standardPlan?: TeamSubSchemaType; onPaySuccess?: () => void; }) => { const { t } = useTranslation(); diff --git a/projects/app/src/web/support/user/team/api.ts b/projects/app/src/web/support/user/team/api.ts index 5a07ebda0..3c3a30a56 100644 --- a/projects/app/src/web/support/user/team/api.ts +++ b/projects/app/src/web/support/user/team/api.ts @@ -18,7 +18,7 @@ import type { } from '@fastgpt/global/support/user/team/type.d'; import type { ClientTeamPlanStatusType, - TeamSubSchema + TeamSubSchemaType } 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'; @@ -113,7 +113,7 @@ export const checkTeamDatasetSizeLimit = (size: number) => export const getTeamPlanStatus = () => GET(`/support/user/team/plan/getTeamPlanStatus`, { maxQuantity: 1 }); export const getTeamPlans = () => - GET(`/proApi/support/user/team/plan/getTeamPlans`); + GET(`/proApi/support/user/team/plan/getTeamPlans`); export const redeemCoupon = (couponCode: string) => GET(`/proApi/support/wallet/coupon/redeem`, { key: couponCode });