feat(user): sync entitlement snapshot

This commit is contained in:
2026-06-29 10:37:37 +08:00
parent 455204e1e4
commit 58cd2a7545
22 changed files with 479 additions and 54 deletions
+2
View File
@@ -9,4 +9,6 @@ export * from "./personality_traits";
export * from "./recent_memory";
export * from "./update_profile_request";
export * from "./user";
export * from "./user_entitlement_snapshot";
export * from "./user_entitlements";
export * from "./user_stats_response";
@@ -0,0 +1,21 @@
/**
* 本地用户权益快照
*
* 只持久化 UI 初始化必须的两个字段,完整权益数据仍由
* `GET /api/user/entitlements` 实时获取。
*/
import { z } from "zod";
import { booleanOrFalse, numberOrZero } from "../nullable-defaults";
export const UserEntitlementSnapshotSchema = z.object({
isVip: booleanOrFalse,
creditBalance: numberOrZero,
});
export type UserEntitlementSnapshotInput = z.input<
typeof UserEntitlementSnapshotSchema
>;
export type UserEntitlementSnapshotData = z.output<
typeof UserEntitlementSnapshotSchema
>;
+105
View File
@@ -0,0 +1,105 @@
/**
* 用户权益快照
*/
import { z } from "zod";
import {
booleanOrFalse,
numberOrZero,
stringOrEmpty,
} from "../nullable-defaults";
export const UserEntitlementsPolicySchema = z
.object({
membershipState: stringOrEmpty,
nonVipEntitlementsShared: booleanOrFalse,
guestSameAsLoggedInNonVip: booleanOrFalse,
refreshAfterPayment: stringOrEmpty,
})
.passthrough();
export const UserEntitlementsCostsSchema = z
.object({
normal_message: numberOrZero,
private_message: numberOrZero,
voice_message: numberOrZero,
photo: numberOrZero,
voice_call_minute: numberOrZero,
private_album_10: numberOrZero,
private_album_20: numberOrZero,
})
.passthrough();
export const UserEntitlementsQuotasSchema = z
.object({
normalChatFreeDaily: numberOrZero,
privateUnlockFreeDaily: numberOrZero,
voiceMessageFreeDaily: numberOrZero,
photoFreeDaily: numberOrZero,
})
.passthrough();
export const UserEntitlementsHistoryUnlockSchema = z
.object({
enabled: booleanOrFalse,
order: stringOrEmpty,
chargeMode: stringOrEmpty,
insufficientBalanceBehavior: stringOrEmpty,
costs: z
.object({
private_message: numberOrZero,
voice_message: numberOrZero,
photo: numberOrZero,
})
.passthrough()
.default(() => ({
private_message: 0,
voice_message: 0,
photo: 0,
})),
})
.passthrough();
export const UserEntitlementsSchema = z.object({
userId: stringOrEmpty,
isGuest: booleanOrFalse,
isVip: booleanOrFalse,
vipExpiresAt: z.string().nullable().default(null),
creditBalance: numberOrZero,
dolBalance: numberOrZero,
policy: UserEntitlementsPolicySchema.default(() => ({
membershipState: "",
nonVipEntitlementsShared: false,
guestSameAsLoggedInNonVip: false,
refreshAfterPayment: "",
})),
costs: UserEntitlementsCostsSchema.default(() => ({
normal_message: 0,
private_message: 0,
voice_message: 0,
photo: 0,
voice_call_minute: 0,
private_album_10: 0,
private_album_20: 0,
})),
quotas: UserEntitlementsQuotasSchema.default(() => ({
normalChatFreeDaily: 0,
privateUnlockFreeDaily: 0,
voiceMessageFreeDaily: 0,
photoFreeDaily: 0,
})),
historyUnlock: UserEntitlementsHistoryUnlockSchema.default(() => ({
enabled: false,
order: "",
chargeMode: "",
insufficientBalanceBehavior: "",
costs: {
private_message: 0,
voice_message: 0,
photo: 0,
},
})),
});
export type UserEntitlementsInput = z.input<typeof UserEntitlementsSchema>;
export type UserEntitlementsData = z.output<typeof UserEntitlementsSchema>;