Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/global/common/error/code/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum TeamErrEnum {
datasetAmountNotEnough = 'datasetAmountNotEnough',
appAmountNotEnough = 'appAmountNotEnough',
pluginAmountNotEnough = 'pluginAmountNotEnough',
appFolderAmountNotEnough = 'appFolderAmountNotEnough',
websiteSyncNotEnough = 'websiteSyncNotEnough',
reRankNotEnough = 'reRankNotEnough',
groupNameEmpty = 'groupNameEmpty',
Expand Down Expand Up @@ -65,6 +66,10 @@ const teamErr = [
statusText: TeamErrEnum.pluginAmountNotEnough,
message: i18nT('common:code_error.team_error.plugin_amount_not_enough')
},
{
statusText: TeamErrEnum.appFolderAmountNotEnough,
message: i18nT('common:code_error.team_error.app_folder_amount_not_enough')
},
{
statusText: TeamErrEnum.websiteSyncNotEnough,
message: i18nT('common:code_error.team_error.website_sync_not_enough')
Expand Down
3 changes: 2 additions & 1 deletion packages/global/common/middle/tracks/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export enum TrackEnum {
datasetSearch = 'datasetSearch',
readSystemAnnouncement = 'readSystemAnnouncement',
clickOperationalAd = 'clickOperationalAd',
closeOperationalAd = 'closeOperationalAd'
closeOperationalAd = 'closeOperationalAd',
teamChatQPM = 'teamChatQPM'
}
31 changes: 30 additions & 1 deletion packages/global/common/string/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const sliceStrStartEnd = (str: string, start: number, end: number) => {
return `${startContent}${overSize ? `\n\n...[hide ${str.length - start - end} chars]...\n\n` : ''}${endContent}`;
};

/*
/*
Parse file extension from url
Test:
1. https://xxx.com/file.pdf?token=123
Expand All @@ -201,3 +201,32 @@ export const parseFileExtensionFromUrl = (url = '') => {
const extension = fileName.split('.').pop();
return (extension || '').toLowerCase();
};

export const formatNumberWithUnit = (num: number, locale: string = 'zh-CN'): string => {
if (num === 0) return '0';
if (!num || isNaN(num)) return '-';
const absNum = Math.abs(num);
const isNegative = num < 0;
const prefix = isNegative ? '-' : '';

if (locale === 'zh-CN') {
if (absNum >= 10000) {
const value = absNum / 10000;
const formatted = Number(value.toFixed(2)).toString();
return `${prefix}${formatted}万`;
}
return num.toLocaleString(locale);
} else {
if (absNum >= 1000000) {
const value = absNum / 1000000;
const formatted = Number(value.toFixed(2)).toString();
return `${prefix}${formatted}M`;
}
if (absNum >= 1000) {
const value = absNum / 1000;
const formatted = Number(value.toFixed(2)).toString();
return `${prefix}${formatted}K`;
}
return num.toLocaleString(locale);
}
};
1 change: 1 addition & 0 deletions packages/global/common/system/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export type FastGPTFeConfigsType = {
show_compliance_copywriting?: boolean;
show_aiproxy?: boolean;
show_coupon?: boolean;
show_discount_coupon?: boolean;
concatMd?: string;

show_dataset_feishu?: boolean;
Expand Down
8 changes: 7 additions & 1 deletion packages/global/openapi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ChatPath } from './core/chat';
import { ApiKeyPath } from './support/openapi';
import { TagsMap } from './tag';
import { PluginPath } from './core/plugin';
import { WalletPath } from './support/wallet';

export const openAPIDocument = createDocument({
openapi: '3.1.0',
Expand All @@ -14,7 +15,8 @@ export const openAPIDocument = createDocument({
paths: {
...ChatPath,
...ApiKeyPath,
...PluginPath
...PluginPath,
...WalletPath
},
servers: [{ url: '/api' }],
'x-tagGroups': [
Expand All @@ -33,6 +35,10 @@ export const openAPIDocument = createDocument({
{
name: 'ApiKey',
tags: [TagsMap.apiKey]
},
{
name: '支付',
tags: [TagsMap.walletBill, TagsMap.walletDiscountCoupon]
}
]
});
81 changes: 81 additions & 0 deletions packages/global/openapi/support/wallet/bill/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { z } from 'zod';
import { ObjectIdSchema } from '../../../../common/type/mongo';
import {
BillTypeEnum,
BillStatusEnum,
BillPayWayEnum
} from '../../../../support/wallet/bill/constants';
import { StandardSubLevelEnum, SubModeEnum } from '../../../../support/wallet/sub/constants';
import { PaginationSchema } from '../../../api';
import { BillSchema } from '../../../../support/wallet/bill/type.d';

export const BillListQuerySchema = PaginationSchema.extend({
type: z.enum(Object.values(BillTypeEnum)).optional().meta({ description: '订单类型筛选' })
});
export type GetBillListQueryType = z.infer<typeof BillListQuerySchema>;

export const BillListResponseSchema = z.object({
total: z.number(),
list: z.array(BillSchema)
});
export type GetBillListResponseType = z.infer<typeof BillListResponseSchema>;

export const CreateStandPlanBillSchema = z.object({
type: z.literal(BillTypeEnum.standSubPlan).meta({ description: '订单类型:标准订阅套餐' }),
level: z.enum(Object.values(StandardSubLevelEnum)).meta({ description: '标准订阅等级' }),
subMode: z.enum(Object.values(SubModeEnum)).meta({ description: '订阅周期' }),
discountCouponId: z.string().optional().meta({ description: '优惠券 ID' })
});
export const CreateExtractPointsBillSchema = z.object({
type: z.literal(BillTypeEnum.extraPoints).meta({ description: '订单类型:额外积分' }),
extraPoints: z.number().meta({ description: '额外积分数量' }),
duration: z.number().meta({ description: '有效期(月)' }),
discountCouponId: z.string().optional().meta({ description: '优惠券 ID(未使用)' })
});
export const CreateExtractDatasetBillSchema = z.object({
type: z.literal(BillTypeEnum.extraDatasetSub).meta({ description: '订单类型:额外数据集存储' }),
extraDatasetSize: z.number().meta({ description: '额外数据集大小' }),
month: z.number().meta({ description: '订阅月数' }),
discountCouponId: z.string().optional().meta({ description: '优惠券 ID(未使用)' })
});
export const CreateBillPropsSchema = z.discriminatedUnion('type', [
CreateStandPlanBillSchema,
CreateExtractPointsBillSchema,
CreateExtractDatasetBillSchema
]);
export type CreateBillPropsType = z.infer<typeof CreateBillPropsSchema>;

export const CreateOrderResponseSchema = z.object({
qrCode: z.string().optional().meta({ description: '支付二维码 URL' }),
iframeCode: z.string().optional().meta({ description: '支付 iframe 代码' }),
markdown: z.string().optional().meta({ description: 'Markdown 格式的支付信息' })
});
export type CreateOrderResponseType = z.infer<typeof CreateOrderResponseSchema>;
export const CreateBillResponseSchema = CreateOrderResponseSchema.extend({
billId: z.string().meta({ description: '订单 ID' }),
readPrice: z.number().meta({ description: '实际支付价格' }),
payment: z.enum(Object.values(BillPayWayEnum)).meta({ description: '支付方式' })
});
export type CreateBillResponseType = z.infer<typeof CreateBillResponseSchema>;

export const CheckPayResultResponseSchema = z.object({
status: z.enum(Object.values(BillStatusEnum)),
description: z.string().optional()
});
export type CheckPayResultResponseType = z.infer<typeof CheckPayResultResponseSchema>;

export const UpdatePaymentPropsSchema = z.object({
billId: ObjectIdSchema,
payWay: z.enum(Object.values(BillPayWayEnum))
});
export type UpdatePaymentPropsType = z.infer<typeof UpdatePaymentPropsSchema>;

export const BillDetailResponseSchema = BillSchema.extend({
couponName: z.string().optional()
});
export type BillDetailResponseType = z.infer<typeof BillDetailResponseSchema>;

export const CancelBillPropsSchema = z.object({
billId: ObjectIdSchema.meta({ description: '订单 ID' })
});
export type CancelBillPropsType = z.infer<typeof CancelBillPropsSchema>;
164 changes: 164 additions & 0 deletions packages/global/openapi/support/wallet/bill/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { z } from 'zod';
import type { OpenAPIPath } from '../../../type';
import {
CreateBillPropsSchema,
CreateBillResponseSchema,
UpdatePaymentPropsSchema,
CreateOrderResponseSchema,
CheckPayResultResponseSchema,
BillDetailResponseSchema,
BillListQuerySchema,
CancelBillPropsSchema
} from './api';
import { TagsMap } from '../../../tag';
import { ObjectIdSchema } from '../../../../common/type/mongo';

export const BillPath: OpenAPIPath = {
'/support/wallet/bill/create': {
post: {
summary: '创建订单',
description: '创建订单订单,支持标准订阅套餐、额外积分、额外数据集存储三种类型',
tags: [TagsMap.walletBill],
requestBody: {
content: {
'application/json': {
schema: CreateBillPropsSchema
}
}
},
responses: {
200: {
description: '成功创建订单',
content: {
'application/json': {
schema: CreateBillResponseSchema
}
}
}
}
}
},
'/support/wallet/bill/detail': {
get: {
summary: '获取订单详情',
description: '根据订单 ID 获取订单详细信息,包括优惠券名称等',
tags: [TagsMap.walletBill],
requestParams: {
query: z.object({
billId: ObjectIdSchema.meta({
description: '订单 ID'
})
})
},
responses: {
200: {
description: '成功获取订单详情',
content: {
'application/json': {
schema: BillDetailResponseSchema.nullable()
}
}
}
}
}
},
'/support/wallet/bill/list': {
post: {
summary: '获取订单列表',
description: '分页获取团队的订单列表,支持按类型筛选',
tags: [TagsMap.walletBill],
requestBody: {
content: {
'application/json': {
schema: BillListQuerySchema
}
}
},
responses: {
200: {
description: '成功获取订单列表',
content: {
'application/json': {
schema: z.object({
list: z.array(BillDetailResponseSchema),
total: z.number().meta({ description: '总数' })
})
}
}
}
}
}
},
'/support/wallet/bill/cancel': {
post: {
summary: '取消订单',
description: '取消未支付的订单,如果使用了优惠券会自动返还',
tags: [TagsMap.walletBill],
requestBody: {
content: {
'application/json': {
schema: CancelBillPropsSchema
}
}
},
responses: {
200: {
description: '成功取消订单',
content: {
'application/json': {
schema: z.null()
}
}
}
}
}
},
'/support/wallet/bill/pay/updatePayment': {
post: {
summary: '更新支付方式',
description: '为未支付的订单更新支付方式,返回新的支付二维码或链接',
tags: [TagsMap.walletBill],
requestBody: {
content: {
'application/json': {
schema: UpdatePaymentPropsSchema
}
}
},
responses: {
200: {
description: '成功更新支付方式',
content: {
'application/json': {
schema: CreateOrderResponseSchema
}
}
}
}
}
},
'/support/wallet/bill/pay/checkPayResult': {
get: {
summary: '检查支付结果',
description: '检查订单的支付状态,用于轮询支付结果',
tags: [TagsMap.walletBill],
requestParams: {
query: z.object({
payId: ObjectIdSchema.meta({
description: '订单 ID'
})
})
},
responses: {
200: {
description: '成功获取支付结果',
content: {
'application/json': {
schema: CheckPayResultResponseSchema
}
}
}
}
}
}
};
33 changes: 33 additions & 0 deletions packages/global/openapi/support/wallet/discountCoupon/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { z } from 'zod';
import { ObjectIdSchema } from '../../../../common/type/mongo';
import {
DiscountCouponStatusEnum,
DiscountCouponTypeEnum
} from '../../../../support/wallet/sub/discountCoupon/constants';

export const DiscountCouponSchema = z.object({
_id: ObjectIdSchema.meta({ description: '优惠券 ID' }),
teamId: ObjectIdSchema.meta({ description: '团队 ID' }),
type: z.enum(Object.values(DiscountCouponTypeEnum)).meta({ description: '优惠券类型' }),
startTime: z.coerce.date().optional().meta({ description: '生效时间' }),
expiredTime: z.coerce.date().meta({ description: '过期时间' }),
usedAt: z.coerce.date().optional().meta({ description: '使用时间' }),
createTime: z.coerce.date().meta({ description: '创建时间' })
});

export type DiscountCouponSchemaType = z.infer<typeof DiscountCouponSchema>;

export const DiscountCouponItemSchema = DiscountCouponSchema.extend({
name: z.string().meta({ description: '优惠券名称' }),
description: z.string().meta({ description: '优惠券描述' }),
discount: z.number().meta({ description: '折扣率' }),
iconZh: z.string().meta({ description: '中文图标路径' }),
iconEn: z.string().meta({ description: '英文图标路径' }),
status: z.enum(Object.values(DiscountCouponStatusEnum)).meta({ description: '优惠券状态' }),
billId: ObjectIdSchema.optional().meta({
description: '关联的订单 ID'
})
});
export const DiscountCouponListResponseSchema = z.array(DiscountCouponItemSchema);

export type DiscountCouponListResponseType = z.infer<typeof DiscountCouponListResponseSchema>;
Loading
Loading