pref: zod schema

This commit is contained in:
archer 2025-12-23 20:52:50 +08:00
parent 02dad3c462
commit 35153e10fa
No known key found for this signature in database
GPG Key ID: 4446499B846D4A9E
10 changed files with 159 additions and 156 deletions

View File

@ -25,6 +25,32 @@ export const BillListResponseSchema = z.object({
});
export type GetBillListResponseType = z.infer<typeof BillListResponseSchema>;
// Bill detail
export const BillDetailQuerySchema = z.object({
billId: ObjectIdSchema.meta({ description: '订单 ID' })
});
export type BillDetailQueryType = z.infer<typeof BillDetailQuerySchema>;
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<typeof BillDetailResponseSchema>;
// Create
export const CreateStandPlanBillSchema = z
.object({
@ -88,30 +114,14 @@ export const CheckPayResultResponseSchema = z.object({
});
export type CheckPayResultResponseType = z.infer<typeof CheckPayResultResponseSchema>;
// 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<typeof BillDetailResponseSchema>;
// Cancel bill
export const CancelBillPropsSchema = z.object({
billId: ObjectIdSchema.meta({ description: '订单 ID' })
});
export type CancelBillPropsType = z.infer<typeof CancelBillPropsSchema>;
// Check pay result
export const CheckPayResultQuerySchema = z.object({
payId: ObjectIdSchema.meta({ description: '订单 ID' })
});
export type CheckPayResultQueryType = z.infer<typeof CheckPayResultQuerySchema>;

View File

@ -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: {

View File

@ -1,5 +1,4 @@
import type { StandardSubLevelEnum, SubModeEnum } from './constants';
import { TeamSubSchema } from './type.d';
export type StandardSubPlanParams = {
level: `${StandardSubLevelEnum}`;

View File

@ -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;
};

View File

@ -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<typeof TeamStandardSubPlanItemSchema>;
export const StandSubPlanLevelMapSchema = z.record(
z.enum(StandardSubLevelEnum),
TeamStandardSubPlanItemSchema
);
export type StandSubPlanLevelMapType = z.infer<typeof StandSubPlanLevelMapSchema>;
export const PointsPackageItemSchema = z.object({
points: z.int(),
month: z.int(),
price: z.number(),
activityBonusPoints: z.int().optional() // 活动赠送积分
});
export type PointsPackageItem = z.infer<typeof PointsPackageItemSchema>;
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<typeof SubPlanSchema>;
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<typeof TeamSubSchema>;
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<typeof TeamPlanStatusSchema>;
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<typeof ClientTeamPlanStatusSchema>;

View File

@ -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<TeamSubSchema>(subCollectionName, SubSchema);
export const MongoTeamSub = getMongoModel<TeamSubSchemaType>(subCollectionName, SubSchema);

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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<ClientTeamPlanStatusType>(`/support/user/team/plan/getTeamPlanStatus`, { maxQuantity: 1 });
export const getTeamPlans = () =>
GET<TeamSubSchema[]>(`/proApi/support/user/team/plan/getTeamPlans`);
GET<TeamSubSchemaType[]>(`/proApi/support/user/team/plan/getTeamPlans`);
export const redeemCoupon = (couponCode: string) =>
GET(`/proApi/support/wallet/coupon/redeem`, { key: couponCode });