diff --git a/apps/web/src/api/points/types.ts b/apps/web/src/api/points/types.ts new file mode 100644 index 000000000..577c26ef1 --- /dev/null +++ b/apps/web/src/api/points/types.ts @@ -0,0 +1,217 @@ +/** + * 积分 & 会员系统 API 类型定义(v2 两档会员制) + * 接口契约对齐后端设计文档 membership-points-design-v2.md + */ + +/** 会员类型 */ +export type MemberType = "free" | "monthly" | "quarterly" | "yearly" + +/** 积分流水类型 */ +export type PointsTxType = "earn" | "spend" | "refund" + +/** 积分来源/消耗场景 */ +export type PointsSource = + | "recharge" // 充值 + | "task_reward" // 任务奖励 + | "ai_voice" // AI 配音 + | "ai_digital_human" // AI 数字人 + | "ai_video" // 智能混剪 + | "voice_clone_train" // 声音克隆训练 + | "voice_clone_synth" // 声音克隆合成 + | "douyin_extract" // 抖音链接提取 + | "ai_rewrite" // AI 改写文案 + | "ai_title" // AI 标题生成 + | "ai_cover" // AI 封面生成 + | "subscription_bonus" // 会员赠送 + | "admin_adjust" // 管理员调整 + | "refund" // 失败退还 + +/** 会员 & 积分余额响应 */ +export interface PointsBalance { + /** 当前可用积分 */ + balance: number + /** 累计获得 */ + total_earned: number + /** 累计消耗 */ + total_spent: number + /** 是否付费会员(free 用户为 false) */ + is_member: boolean + /** 会员类型:monthly / quarterly / yearly;free 用户为 null */ + member_type: Extract | null + /** 会员到期时间 ISO 字符串 */ + member_expires_at: string | null + /** 今日免费混剪已用次数 */ + free_clips_used?: number + /** 今日免费混剪额度上限 */ + free_clips_limit?: number + /** 今日免费混剪剩余 */ + free_clips_remaining?: number +} + +/** 积分流水记录 */ +export interface PointsTransaction { + id: string + /** earn / spend / refund */ + type: PointsTxType + /** 来源场景 */ + source: PointsSource + /** 场景中文名称 */ + source_name: string + /** 变动数量(正数) */ + amount: number + /** 带符号的变动数(收入+,支出-) */ + signed_amount: number + /** 变动后余额 */ + balance_after: number + /** 备注描述 */ + description: string + /** 关联业务 ID */ + ref_id: string | null + created_at: string +} + +/** 积分流水分页响应 */ +export interface PointsTransactionsResponse { + items: PointsTransaction[] + total: number + page: number + page_size: number +} + +/** 积分流水查询参数 */ +export interface PointsTransactionsParams { + page?: number + page_size?: number + type?: PointsTxType + source?: PointsSource + start_date?: string + end_date?: string +} + +/** 积分包 */ +export interface PointsPackage { + id: "starter_pack" | "basic_pack" | "pro_pack" | string + /** 中文名称 */ + name: string + /** 积分数量 */ + points: number + /** 原价(分) */ + price: number + /** 各会员类型折扣价(分) */ + discounted_price_for_free: number + discounted_price_for_monthly: number + discounted_price_for_quarterly: number + discounted_price_for_yearly: number +} + +/** 积分包列表响应 */ +export interface PointsPackagesResponse { + packages: PointsPackage[] + /** 当前用户会员类型,用于前端计算折后价 */ + user_member_type: MemberType + /** 积分单价(元/积分,按会员价计) */ + unit_price_yuan: number +} + +/** 创建充值订单请求 */ +export interface PointsRechargeRequest { + package_id: string + payment_method?: "wechat_pay" | "alipay" +} + +/** 订单状态 */ +export type OrderStatus = "pending" | "paid" | "failed" | "refunded" | "expired" + +/** 充值订单响应 */ +export interface PointsOrder { + id: string + package_id: string + package_name: string + points_amount: number + price_cents: number + original_price_cents: number + discount: number + currency: "CNY" + status: OrderStatus + payment_method: string | null + payment_id: string | null + paid_at: string | null + expire_at: string | null + created_at: string + /** 微信/支付宝支付参数(mock 阶段前端自行处理) */ + pay_params?: Record +} + +/** 订阅套餐(月/季/年) */ +export interface SubscriptionPlan { + id: "monthly" | "quarterly" | "yearly" + name: string + price_cents: number + price_yuan: number + per_month_yuan: number + savings_percent?: number + recommended?: boolean + billing_label: string +} + +/** 当前订阅详情 */ +export interface SubscriptionCurrent { + is_member: boolean + member_type: Extract | null + member_type_name: string + status: "active" | "expired" | "cancelled" | "none" + current_period_start: string | null + current_period_end: string | null + auto_renew: boolean + /** 订阅会员对应的积分折扣 */ + points_discount: number +} + +/** 开通/续费订阅请求 */ +export interface SubscribeRequest { + member_type: "monthly" | "quarterly" | "yearly" + payment_method?: "wechat_pay" | "alipay" +} + +/** 积分消耗规则 */ +export interface PointsRule { + scene_key: PointsSource + scene_name: string + /** 每次消耗基础积分(会员价) */ + points_per_use: number + /** 计量单位:条/分钟/次/张 */ + unit: string + /** 额外每 30s 加积分(ai_video 用) */ + extra_per_30s?: number + /** 说明文案 */ + description?: string +} + +export interface PointsRulesResponse { + rules: PointsRule[] + /** 免费用户消耗倍率 */ + free_user_multiplier: number + note: string +} + +/** 消费前余额检查请求 */ +export interface PointsCheckRequest { + scene_key: PointsSource + /** 单位数量(时长/条数),默认 1 */ + units?: number +} + +/** 消费前余额检查响应 */ +export interface PointsCheckResponse { + allowed: boolean + required_points: number + current_balance: number + remaining_after: number + /** 是否走免费额度(混剪场景) */ + is_free_quota: boolean + /** 拒绝原因代码 */ + code?: "INSUFFICIENT_POINTS" | "FREE_QUOTA_EXCEEDED" | "SCENE_NOT_FOUND" + message?: string + /** 充值页跳转 URL */ + recharge_url?: string +}