diff --git a/src/app/subscription/success/page.tsx b/src/app/subscription/success/page.tsx index 52956695..17e5ca21 100644 --- a/src/app/subscription/success/page.tsx +++ b/src/app/subscription/success/page.tsx @@ -5,18 +5,18 @@ * 流程: * 1. 用户在支付服务托管页完成结账 * 2. 支付服务重定向到 `/subscription/success` - * 3. 这个页面显示 "购买成功" + 调 `getCurrentUser` 刷新 user + * 3. 这个页面显示 "购买成功" + 调 VIP 状态接口确认权益 * 4. 点 "返回订阅页" 跳回 `/subscription` * * 注意:权益发放由后端支付服务链路异步完成。 - * 此页面轮询几次 getCurrentUser 等待 user 状态完成更新。 + * 此页面轮询几次 VIP 状态接口等待权益完成更新。 */ import { useEffect, useRef, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { MobileShell } from "@/app/_components/core/mobile-shell"; -import { authRepository } from "@/data/repositories/auth_repository"; +import { paymentRepository } from "@/data/repositories/payment_repository"; import { ROUTES } from "@/router/routes"; export default function SubscriptionSuccessPage() { @@ -25,7 +25,7 @@ export default function SubscriptionSuccessPage() { const [errorMessage, setErrorMessage] = useState(null); const hasRefreshed = useRef(false); - // 轮询 getCurrentUser 等待后端权益发放完成 + // 轮询 VIP 状态接口等待后端权益发放完成 useEffect(() => { if (hasRefreshed.current) return; hasRefreshed.current = true; @@ -33,7 +33,7 @@ export default function SubscriptionSuccessPage() { let cancelled = false; const tryRefresh = async (attemptsLeft: number) => { if (cancelled) return; - const r = await authRepository.getCurrentUser(); + const r = await paymentRepository.getVipStatus(); if (cancelled) return; if (r.success) { if (r.data.isVip) { diff --git a/src/data/dto/user/__tests__/user.test.ts b/src/data/dto/user/__tests__/user.test.ts new file mode 100644 index 00000000..3e20624d --- /dev/null +++ b/src/data/dto/user/__tests__/user.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from "vitest"; + +import { User } from "@/data/dto/user/user"; + +describe("User", () => { + it("parses the latest backend user payload", () => { + const user = User.fromJson({ + id: "d7bb2b3d-e9c5-474c-85fe-f503048f30dd", + username: "guest_bbc90a38", + email: "device_bbc90a38b996187348f54cf2cb0b789e@guest.local", + platform: "web", + intimacy: 0, + dolBalance: 0, + personalityTraits: { + caring: 0.5, + playful: 0.5, + serious: 0.5, + cheerful: 0.5, + romantic: 0.5, + }, + preferredLanguage: "zh", + createdAt: "2026-06-12T08:08:27.378706+00:00", + lastMessageAt: "2026-06-24T11:00:23.156561+00:00", + }); + + expect(user.toJson()).toEqual({ + id: "d7bb2b3d-e9c5-474c-85fe-f503048f30dd", + username: "guest_bbc90a38", + email: "device_bbc90a38b996187348f54cf2cb0b789e@guest.local", + platform: "web", + intimacy: 0, + dolBalance: 0, + personalityTraits: { + caring: 0.5, + playful: 0.5, + serious: 0.5, + cheerful: 0.5, + romantic: 0.5, + }, + preferredLanguage: "zh", + createdAt: "2026-06-12T08:08:27.378706+00:00", + lastMessageAt: "2026-06-24T11:00:23.156561+00:00", + }); + }); +}); diff --git a/src/data/dto/user/user.ts b/src/data/dto/user/user.ts index 4840a3b4..9938d74f 100644 --- a/src/data/dto/user/user.ts +++ b/src/data/dto/user/user.ts @@ -15,19 +15,10 @@ export class User { declare readonly platform: string; declare readonly intimacy: number; declare readonly dolBalance: number; - declare readonly relationshipStage: string; - declare readonly currentMood: string; declare readonly personalityTraits: PersonalityTraits; declare readonly preferredLanguage: string; declare readonly createdAt: string; declare readonly lastMessageAt: string; - declare readonly avatarUrl: string; - declare readonly loginProvider: string; - declare readonly isGuest: boolean; - /** 是否为 VIP 会员 */ - declare readonly isVip: boolean; - /** 语音聊天剩余分钟数 */ - declare readonly voiceMinutesRemaining: number; private constructor(input: UserInput) { const data = UserSchema.parse(input); diff --git a/src/data/schemas/user/user.ts b/src/data/schemas/user/user.ts index 6f5cd903..a49a0adf 100644 --- a/src/data/schemas/user/user.ts +++ b/src/data/schemas/user/user.ts @@ -5,7 +5,6 @@ import { z } from "zod"; import { PersonalityTraitsSchema, PERSONALITY_TRAITS_DEFAULTS } from "./personality_traits"; import { - booleanOrFalse, numberOrZero, stringOrEmpty, } from "../nullable-defaults"; @@ -17,20 +16,11 @@ export const UserSchema = z.object({ platform: stringOrEmpty, intimacy: numberOrZero, dolBalance: numberOrZero, - relationshipStage: stringOrEmpty, - currentMood: stringOrEmpty, personalityTraits: PersonalityTraitsSchema.default(PERSONALITY_TRAITS_DEFAULTS), preferredLanguage: stringOrEmpty, createdAt: stringOrEmpty, // 后端新游客返回 null("还没发过消息"),前端统一收敛为空字符串。 lastMessageAt: stringOrEmpty, - avatarUrl: stringOrEmpty, - loginProvider: stringOrEmpty, - isGuest: booleanOrFalse, - /** 是否为 VIP 会员(订阅中或未过期) */ - isVip: booleanOrFalse, - /** 语音聊天剩余分钟数(订阅生效后每天补充;用完为 0 不变) */ - voiceMinutesRemaining: numberOrZero, }); export type UserInput = z.input;