chore(契约): 三池余额 DTO 交给 ts-rs 生成,同步 SpacetimeDB 绑定
- 给 ProfileMudPointBalanceResponse 加 ts-bindings 特性下的 ts_rs::TS 导出,u64 标 ts(type = "number") 避免前端分叉成 bigint - 新增 packages/shared/src/contracts/generated/ProfileMudPointBalanceResponse.ts,runtime.ts 改为 re-export 不再手写第二份字段 - 新增 packages/shared/src/utils/mudPoints.ts:派生展示用合计与北京时间月度刷新文案 - 同步 spacetime-client 生成绑定:升级报价改名为 snapshot,与 module 侧改动对齐 Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ProfileMudPointBalanceResponse = {
|
||||
/**
|
||||
* 每日免费泥点:北京业务日有效,跨日清零并重置。
|
||||
*/
|
||||
dailyFreePoints: number;
|
||||
dailyFreeResetPoints: number;
|
||||
dailyFreeResetsAt: string;
|
||||
/**
|
||||
* 月度泥点:会员每期额度,到刷新时刻清零再发新额度。
|
||||
*/
|
||||
monthlyPoints: number;
|
||||
monthlyResetsAt: string | null;
|
||||
/**
|
||||
* 永久泥点:不过期,创作照常扣点。
|
||||
*/
|
||||
permanentPoints: number;
|
||||
};
|
||||
@@ -1,4 +1,7 @@
|
||||
import type { JsonObject } from './common';
|
||||
import type { ProfileMudPointBalanceResponse as ProfileMudPointBalance } from './generated/ProfileMudPointBalanceResponse';
|
||||
|
||||
export type { ProfileMudPointBalance };
|
||||
|
||||
export const SAVE_SNAPSHOT_VERSION = 2;
|
||||
export const DEFAULT_MUSIC_VOLUME = 0.42;
|
||||
@@ -118,15 +121,17 @@ export type ExternalApiKeyMutationResponse = {
|
||||
|
||||
export type ProfileRechargeProductKind = 'points' | 'membership';
|
||||
export type ProfileMembershipStatus = 'normal' | 'active';
|
||||
export type ProfileMembershipTier =
|
||||
/** 会员档位:`normal` 是非会员占位档位,不可购买。 */
|
||||
export type ProfileMembershipPlan =
|
||||
| 'normal'
|
||||
| 'month'
|
||||
| 'season'
|
||||
| 'year'
|
||||
| 'starter'
|
||||
| 'basic'
|
||||
| 'plus'
|
||||
| 'pro'
|
||||
| 'ultimate';
|
||||
| 'max';
|
||||
/** 会员周期:有效期内不支持月年互换,到期后重新选择。 */
|
||||
export type ProfileMembershipCycleKind = 'monthly' | 'yearly';
|
||||
/** 模型权限:`basic` 仅基础模型,`full` 基础及高性能模型。 */
|
||||
export type ProfileMembershipModelAccess = 'basic' | 'full';
|
||||
export type ProfileRechargeOrderStatus =
|
||||
| 'pending'
|
||||
| 'paid'
|
||||
@@ -145,28 +150,27 @@ export type ProfileRechargeProduct = {
|
||||
durationDays: number;
|
||||
badgeLabel: string;
|
||||
description: string;
|
||||
tier: ProfileMembershipTier;
|
||||
membershipPeriodPoints: number;
|
||||
membershipPeriodDays: number;
|
||||
membershipQueueLimit: number;
|
||||
membershipDiscountBps: number;
|
||||
};
|
||||
|
||||
export type ProfileMembershipBenefit = {
|
||||
benefitName: string;
|
||||
normalValue: string;
|
||||
monthValue: string;
|
||||
seasonValue: string;
|
||||
yearValue: string;
|
||||
starterValue: string;
|
||||
basicValue: string;
|
||||
proValue: string;
|
||||
ultimateValue: string;
|
||||
/** 会员档位目录行;价格与权益的唯一真相源是后端 `profile_membership_plan` 表。 */
|
||||
export type ProfileMembershipPlanRecord = {
|
||||
plan: ProfileMembershipPlan;
|
||||
title: string;
|
||||
rank: number;
|
||||
monthPriceCents: number;
|
||||
yearPriceCents: number;
|
||||
periodPoints: number;
|
||||
modelAccess: ProfileMembershipModelAccess;
|
||||
/** 并发上限;`128` 表示不设上限。 */
|
||||
concurrentJobLimit: number;
|
||||
sortOrder: number;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type ProfileMembership = {
|
||||
status: ProfileMembershipStatus;
|
||||
tier: ProfileMembershipTier;
|
||||
/** 当前档位;非会员与已到期都是 `normal`。 */
|
||||
plan: ProfileMembershipPlan;
|
||||
startedAt: string | null;
|
||||
expiresAt: string | null;
|
||||
updatedAt: string | null;
|
||||
@@ -174,17 +178,29 @@ export type ProfileMembership = {
|
||||
cycleResetsAt: string | null;
|
||||
cycleGrantedPoints: number;
|
||||
cycleRemainingPoints: number;
|
||||
cyclePeriodDays: number;
|
||||
/** 当前期序号(1-based)。 */
|
||||
cycleIndex: number;
|
||||
/** 本次购买总期数(月付 1 / 年付 12)。 */
|
||||
cycleCount: number;
|
||||
cycleKind: ProfileMembershipCycleKind;
|
||||
};
|
||||
|
||||
export type ProfileMudPointBalance = {
|
||||
totalPoints: number;
|
||||
permanentPoints: number;
|
||||
limitedPoints: number;
|
||||
limitedExpiresAt: string | null;
|
||||
dailyFreePoints: number;
|
||||
dailyFreeResetPoints: number;
|
||||
dailyFreeResetsAt: string;
|
||||
/** 补差升级报价;下单时后端会用同一套规则重算,前端展示的数字不是真相源。 */
|
||||
export type ProfileMembershipUpgradeQuote = {
|
||||
currentPlan: ProfileMembershipPlan;
|
||||
targetPlan: ProfileMembershipPlan;
|
||||
cycleKind: ProfileMembershipCycleKind;
|
||||
cycleIndex: number;
|
||||
cycleCount: number;
|
||||
/** 应付金额(分)。 */
|
||||
amountCents: number;
|
||||
/** 本期补点。 */
|
||||
grantedPointsDelta: number;
|
||||
/** 变更后月度余额 = 原剩余月度余额 + 补点。 */
|
||||
monthlyBalanceAfter: number;
|
||||
expiresAt: string | null;
|
||||
cycleResetsAt: string | null;
|
||||
remainingFullMonths: number;
|
||||
};
|
||||
|
||||
export type ProfileRechargeOrder = {
|
||||
@@ -207,13 +223,12 @@ export type ProfileRechargeOrder = {
|
||||
};
|
||||
|
||||
export type ProfileRechargeCenterResponse = {
|
||||
walletBalance: number;
|
||||
// TODO mirror backend: should not nullable
|
||||
mudPointBalance?: ProfileMudPointBalance;
|
||||
membership: ProfileMembership;
|
||||
pointProducts: ProfileRechargeProduct[];
|
||||
membershipProducts: ProfileRechargeProduct[];
|
||||
benefits: ProfileMembershipBenefit[];
|
||||
/** 会员档位目录(后台可改价);会员购买 / 升级的价格与权益以它为准。 */
|
||||
membershipPlans: ProfileMembershipPlanRecord[];
|
||||
latestOrder: ProfileRechargeOrder | null;
|
||||
hasPointsRecharged: boolean;
|
||||
dailyFreePoints?: ProfileDailyFreePoints;
|
||||
|
||||
@@ -12,4 +12,5 @@ export * from './http';
|
||||
export * from './llm/narrativeLanguage';
|
||||
export * from './llm/parsers';
|
||||
export * from './stores/createProfileWalletStore';
|
||||
export * from './utils/mudPoints';
|
||||
export * from './utils/signedReadUrlCache';
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { ProfileMudPointBalance } from '../contracts/runtime';
|
||||
|
||||
/**
|
||||
* 泥点余额的展示视图。
|
||||
*
|
||||
* 后端只并列暴露三个池子(每日免费 / 月度 / 永久),**不**提供「可用总额」字段,
|
||||
* 以「合计」与「可用」的口径散回后端或各自相加都会分叉。需要合计展示时统一走
|
||||
* {@link resolveProfileMudPointBalanceView}。
|
||||
*/
|
||||
export type ProfileMudPointBalanceView = ProfileMudPointBalance & {
|
||||
/** 每日免费 + 月度 + 永久;只用于展示,不代表「可用额度」。 */
|
||||
totalPoints: number;
|
||||
};
|
||||
|
||||
export function resolveProfileMudPointBalanceView(
|
||||
balance: ProfileMudPointBalance,
|
||||
): ProfileMudPointBalanceView {
|
||||
// 三个池子按 0 兜底:接口缺字段时宁可显示 0,也不能让合计变成 NaN。
|
||||
return {
|
||||
...balance,
|
||||
dailyFreePoints: balance.dailyFreePoints ?? 0,
|
||||
monthlyPoints: balance.monthlyPoints ?? 0,
|
||||
permanentPoints: balance.permanentPoints ?? 0,
|
||||
totalPoints:
|
||||
(balance.dailyFreePoints ?? 0) +
|
||||
(balance.monthlyPoints ?? 0) +
|
||||
(balance.permanentPoints ?? 0),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 从任意余额形状推导展示用合计;三池缺省按 0 处理,整体为 `undefined` 时返回 `undefined`。
|
||||
*/
|
||||
export function resolveProfileMudPointDisplayTotal(
|
||||
balance: ProfileMudPointBalance | null | undefined,
|
||||
): number | undefined {
|
||||
if (!balance) {
|
||||
return undefined;
|
||||
}
|
||||
return resolveProfileMudPointBalanceView(balance).totalPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* 月度泥点的刷新时刻展示文案。
|
||||
*
|
||||
* 账期锚点按北京时间定义(见 ADR「会员账期按开通日自然月」),所以展示也固定用北京时间,
|
||||
* 不随设备时区漂移;无会员周期或时间非法时返回 `null`,由调用方给兜底说明。
|
||||
*/
|
||||
export function formatMudPointResetAt(
|
||||
value: string | null | undefined,
|
||||
): string | null {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
const parsed = new Date(value);
|
||||
if (Number.isNaN(parsed.getTime())) {
|
||||
return null;
|
||||
}
|
||||
const parts = new Intl.DateTimeFormat('en-CA', {
|
||||
timeZone: 'Asia/Shanghai',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false,
|
||||
}).formatToParts(parsed);
|
||||
const lookup = (type: Intl.DateTimeFormatPartTypes) =>
|
||||
parts.find((part) => part.type === type)?.value ?? '00';
|
||||
return `${lookup('year')}-${lookup('month')}-${lookup('day')} ${lookup('hour')}:${lookup(
|
||||
'minute',
|
||||
)}`;
|
||||
}
|
||||
@@ -201,15 +201,30 @@ pub struct ProfileDailyFreePointsResponse {
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "ts-bindings", derive(ts_rs::TS))]
|
||||
#[cfg_attr(
|
||||
feature = "ts-bindings",
|
||||
ts(
|
||||
export,
|
||||
export_to = concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/../../../packages/shared/src/contracts/generated/"
|
||||
)
|
||||
)
|
||||
)]
|
||||
pub struct ProfileMudPointBalanceResponse {
|
||||
/// 每日免费泥点:北京业务日有效,跨日清零并重置。
|
||||
#[cfg_attr(feature = "ts-bindings", ts(type = "number"))]
|
||||
pub daily_free_points: u64,
|
||||
#[cfg_attr(feature = "ts-bindings", ts(type = "number"))]
|
||||
pub daily_free_reset_points: u64,
|
||||
pub daily_free_resets_at: String,
|
||||
/// 月度泥点:会员每期额度,到刷新时刻清零再发新额度。
|
||||
#[cfg_attr(feature = "ts-bindings", ts(type = "number"))]
|
||||
pub monthly_points: u64,
|
||||
pub monthly_resets_at: Option<String>,
|
||||
/// 永久泥点:不过期,创作照常扣点。
|
||||
#[cfg_attr(feature = "ts-bindings", ts(type = "number"))]
|
||||
pub permanent_points: u64,
|
||||
}
|
||||
|
||||
|
||||
@@ -665,7 +665,7 @@ pub mod runtime_profile_membership_snapshot_type;
|
||||
pub mod runtime_profile_membership_status_type;
|
||||
pub mod runtime_profile_membership_upgrade_quote_get_input_type;
|
||||
pub mod runtime_profile_membership_upgrade_quote_procedure_result_type;
|
||||
pub mod runtime_profile_membership_upgrade_quote_record_type;
|
||||
pub mod runtime_profile_membership_upgrade_quote_snapshot_type;
|
||||
pub mod runtime_profile_recharge_center_get_input_type;
|
||||
pub mod runtime_profile_recharge_center_procedure_result_type;
|
||||
pub mod runtime_profile_recharge_center_snapshot_type;
|
||||
@@ -1482,7 +1482,7 @@ pub use runtime_profile_membership_snapshot_type::RuntimeProfileMembershipSnapsh
|
||||
pub use runtime_profile_membership_status_type::RuntimeProfileMembershipStatus;
|
||||
pub use runtime_profile_membership_upgrade_quote_get_input_type::RuntimeProfileMembershipUpgradeQuoteGetInput;
|
||||
pub use runtime_profile_membership_upgrade_quote_procedure_result_type::RuntimeProfileMembershipUpgradeQuoteProcedureResult;
|
||||
pub use runtime_profile_membership_upgrade_quote_record_type::RuntimeProfileMembershipUpgradeQuoteRecord;
|
||||
pub use runtime_profile_membership_upgrade_quote_snapshot_type::RuntimeProfileMembershipUpgradeQuoteSnapshot;
|
||||
pub use runtime_profile_recharge_center_get_input_type::RuntimeProfileRechargeCenterGetInput;
|
||||
pub use runtime_profile_recharge_center_procedure_result_type::RuntimeProfileRechargeCenterProcedureResult;
|
||||
pub use runtime_profile_recharge_center_snapshot_type::RuntimeProfileRechargeCenterSnapshot;
|
||||
|
||||
+2
-2
@@ -4,13 +4,13 @@
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
use super::runtime_profile_membership_upgrade_quote_record_type::RuntimeProfileMembershipUpgradeQuoteRecord;
|
||||
use super::runtime_profile_membership_upgrade_quote_snapshot_type::RuntimeProfileMembershipUpgradeQuoteSnapshot;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct RuntimeProfileMembershipUpgradeQuoteProcedureResult {
|
||||
pub ok: bool,
|
||||
pub quote: Option<RuntimeProfileMembershipUpgradeQuoteRecord>,
|
||||
pub quote: Option<RuntimeProfileMembershipUpgradeQuoteSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct RuntimeProfileMembershipUpgradeQuoteRecord {
|
||||
pub struct RuntimeProfileMembershipUpgradeQuoteSnapshot {
|
||||
pub current_plan: String,
|
||||
pub target_plan: String,
|
||||
pub cycle_kind: String,
|
||||
@@ -20,6 +20,6 @@ pub struct RuntimeProfileMembershipUpgradeQuoteRecord {
|
||||
pub remaining_full_months: u32,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for RuntimeProfileMembershipUpgradeQuoteRecord {
|
||||
impl __sdk::InModule for RuntimeProfileMembershipUpgradeQuoteSnapshot {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
Reference in New Issue
Block a user