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 */