drama.js 2.06 KB
import * as v from 'valibot'

/**
 * 付费墙描述:drama 是否/如何收费(剧情线/结局解锁)。
 * `unlock_cost`/`user_credits`/`vip_tier` 由 server(S2 sk-facade)按需下发,驱动解锁弹窗的
 * 「需 N 点 · 你有 M 点」与「开 VIP」指向;全为可选,缺省时弹窗降级为纯订阅引导。
 * @typedef {{
 *   locked: boolean,
 *   price?: number,
 *   currency?: string,
 *   unlock_cost?: number,
 *   user_credits?: number,
 *   vip_tier?: string
 * }} PaywallT
 */
export const Paywall = v.object({
  locked: v.boolean(),
  price: v.optional(v.number()),
  currency: v.optional(v.string()),
  /** 解锁本条剧情线所需点数(后端按规则计算下发)。 */
  unlock_cost: v.optional(v.number()),
  /** 当前账户点数余额(解锁弹窗实时显示,禁用判定依据)。 */
  user_credits: v.optional(v.number()),
  /** 「开通 VIP」指向的档位标识(如 vip-yearly)。 */
  vip_tier: v.optional(v.string()),
})

/**
 * drama 列表项形状:Feed 刷剧与剧本库共用。
 * @typedef {{
 *   id: string,
 *   title: string,
 *   cover: string,
 *   locale: string,
 *   heat?: number,
 *   paywall?: PaywallT
 * }} DramaT
 */
export const Drama = v.object({
  id: v.string(),
  title: v.string(),
  cover: v.string(),
  locale: v.string(),
  heat: v.optional(v.number()),
  paywall: v.optional(Paywall),
})

/**
 * 高阶分页信封工厂:`Page(itemSchema)` 产出该 item 的分页 schema,复用同一信封结构。
 * 统一分页形状供 Feed / 剧本库等所有列表接口共用。
 * @param {import('valibot').GenericSchema} itemSchema 任意 item 的 Valibot schema
 * @returns {import('valibot').GenericSchema} 该 item 的分页信封 schema
 */
export function Page(itemSchema) {
  return v.object({
    items: v.array(itemSchema),
    page: v.number(),
    page_size: v.number(),
    total: v.number(),
    has_more: v.boolean(),
  })
}

/**
 * 分页信封类型(泛型 item)。
 * @template T
 * @typedef {{ items: T[], page: number, page_size: number, total: number, has_more: boolean }} PageT
 */