AGC 桌面壳接入会员升级报价与会员下单

- 新增 Tauri 命令 read_profile_membership_upgrade_quote 并注册到桌面端
- accountHost 新增会员升级报价调用
- useAccountWallet 与 AccountWallet 接通报价、会员下单与共享弹层新 props
- 补充 accountHost 报价调用测试

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-10-03 12:12:18 +08:00
parent f33d11b050
commit 6b4b248879
6 changed files with 121 additions and 3 deletions
@@ -12,8 +12,9 @@ use serde::Serialize;
use serde_json::Value;
use shared_contracts::runtime::{
ConfirmWechatProfileRechargeOrderResponse, CreateProfileRechargeOrderResponse,
ProfileRechargeCenterResponse, ProfileReferralInviteCenterResponse,
ProfileWalletLedgerResponse, RedeemProfileRewardCodeResponse,
ProfileMembershipUpgradeQuoteResponse, ProfileRechargeCenterResponse,
ProfileReferralInviteCenterResponse, ProfileWalletLedgerResponse,
RedeemProfileRewardCodeResponse,
};
use std::time::Duration;
use url::Url;
@@ -181,6 +182,24 @@ pub(crate) async fn read_profile_recharge_center() -> Result<ProfileRechargeCent
.await
}
#[tauri::command]
pub(crate) async fn read_profile_membership_upgrade_quote(
target_plan: String,
) -> Result<ProfileMembershipUpgradeQuoteResponse, String> {
let target_plan = bounded_business_id(&target_plan, "会员档位")?;
let snapshot = require_session()?;
let client = build_client()?;
request_json(
&client,
&snapshot,
Method::POST,
&["api", "profile", "membership", "upgrade-quote"],
Some(serde_json::json!({ "targetPlan": target_plan })),
"读取升级报价失败",
)
.await
}
#[tauri::command]
pub(crate) async fn read_profile_wallet_ledger() -> Result<ProfileWalletLedgerResponse, String> {
let snapshot = require_session()?;
@@ -637,6 +637,7 @@ pub(super) fn run() {
set_chat_prompt_polish_reminder_disabled,
set_client_server_selection,
read_profile_recharge_center,
read_profile_membership_upgrade_quote,
read_profile_wallet_ledger,
read_profile_referral_invite_center,
create_profile_recharge_order,
@@ -42,9 +42,18 @@ export function AccountWalletDialogs({
error={controller.rechargeError}
submittingProductId={controller.submittingRechargeProductId}
nativePayment={controller.nativeRechargePayment}
membershipQuote={controller.membershipQuote}
isLoadingMembershipQuote={controller.membershipQuoteLoading}
membershipQuoteError={controller.membershipQuoteError}
onClose={controller.closeRecharge}
onRetry={() => void controller.loadRechargeCenter()}
onBuy={(product) => void controller.buyRechargeProduct(product)}
onRequestMembershipQuote={(plan) =>
void controller.requestMembershipQuote(plan)
}
onSubmitMembershipCheckout={(plan, cycleKind) =>
controller.submitMembershipCheckout(plan, cycleKind)
}
onConfirmNativePayment={() =>
void controller.confirmNativeRechargePayment()
}
@@ -1,7 +1,11 @@
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import type { PlatformProfileRechargeNativePaymentState } from '../../../../../packages/shared/src/components/PlatformProfileRechargeModal';
import { type PlatformProfileRechargeNativePaymentState } from '../../../../../packages/shared/src/components/PlatformProfileRechargeModal';
import { resolveMembershipProductId } from '../../../../../packages/shared/src/components/PlatformProfileRechargeModal/membershipProduct';
import type {
ProfileMembershipCycleKind,
ProfileMembershipPlan,
ProfileMembershipUpgradeQuote,
ProfileRechargeCenterResponse,
ProfileRechargeProduct,
ProfileWalletLedgerResponse,
@@ -10,6 +14,7 @@ import type { RechargeContent } from '../../app/types';
import {
confirmClientWechatProfileRechargeOrder,
createClientProfileRechargeOrder,
getClientProfileMembershipUpgradeQuote,
getClientProfileRechargeCenter,
getClientProfileWalletLedger,
redeemClientProfileRewardCode,
@@ -45,6 +50,12 @@ export function useAccountWallet(currentUserId: string) {
useState<string | null>(null);
const [nativeRechargePayment, setNativeRechargePayment] =
useState<PlatformProfileRechargeNativePaymentState | null>(null);
const [membershipQuote, setMembershipQuote] =
useState<ProfileMembershipUpgradeQuote | null>(null);
const [membershipQuoteLoading, setMembershipQuoteLoading] = useState(false);
const [membershipQuoteError, setMembershipQuoteError] = useState<
string | null
>(null);
const [redeemCodeOpen, setRedeemCodeOpen] = useState(false);
const [redeemCodeInput, setRedeemCodeInput] = useState('');
const [redeemCodeLoading, setRedeemCodeLoading] = useState(false);
@@ -111,6 +122,9 @@ export function useAccountWallet(currentUserId: string) {
setRechargeError(null);
setSubmittingRechargeProductId(null);
setNativeRechargePayment(null);
setMembershipQuote(null);
setMembershipQuoteLoading(false);
setMembershipQuoteError(null);
redeemLifecycleRef.current += 1;
setRedeemCodeOpen(false);
setRedeemCodeInput('');
@@ -217,6 +231,9 @@ export function useAccountWallet(currentUserId: string) {
setRechargeOpen(false);
setNativeRechargePayment(null);
setSubmittingRechargeProductId(null);
setMembershipQuote(null);
setMembershipQuoteLoading(false);
setMembershipQuoteError(null);
}
function openRedeemCode() {
@@ -375,6 +392,59 @@ export function useAccountWallet(currentUserId: string) {
}
}
async function requestMembershipQuote(plan: ProfileMembershipPlan) {
const rechargeLifecycle = rechargeLifecycleRef.current;
const snapshotOwnerUserId = currentUserId;
setMembershipQuote(null);
setMembershipQuoteError(null);
setMembershipQuoteLoading(true);
try {
const quote = await getClientProfileMembershipUpgradeQuote(plan);
if (
rechargeLifecycleRef.current !== rechargeLifecycle ||
currentUserIdRef.current !== snapshotOwnerUserId
) {
return;
}
setMembershipQuote(quote);
} catch (error) {
if (
rechargeLifecycleRef.current === rechargeLifecycle &&
currentUserIdRef.current === snapshotOwnerUserId
) {
setMembershipQuoteError(
error instanceof Error ? error.message : '读取升级报价失败',
);
}
} finally {
if (
rechargeLifecycleRef.current === rechargeLifecycle &&
currentUserIdRef.current === snapshotOwnerUserId
) {
setMembershipQuoteLoading(false);
}
}
}
function submitMembershipCheckout(
plan: ProfileMembershipPlan,
cycleKind: ProfileMembershipCycleKind,
) {
// 会员商品没有商品配置行:标题与价格由后端按档位与周期现算,
// 这里只需要把 productId 交给同一条下单链路。
void buyRechargeProduct({
productId: resolveMembershipProductId(plan, cycleKind),
title: plan,
priceCents: 0,
kind: 'membership',
pointsAmount: 0,
bonusPoints: 0,
durationDays: 0,
badgeLabel: '',
description: '',
});
}
return {
ownerUserId,
mudPointBalance: visibleMudPointBalance,
@@ -402,6 +472,11 @@ export function useAccountWallet(currentUserId: string) {
? submittingRechargeProductId
: null,
nativeRechargePayment: walletUiIsVisible ? nativeRechargePayment : null,
membershipQuote: walletUiIsVisible ? membershipQuote : null,
membershipQuoteLoading: walletUiIsVisible && membershipQuoteLoading,
membershipQuoteError: walletUiIsVisible ? membershipQuoteError : null,
requestMembershipQuote,
submitMembershipCheckout,
setNativeRechargePayment,
loadWalletLedger,
openWalletLedger,
@@ -1,6 +1,8 @@
import type {
ConfirmWechatProfileRechargeOrderResponse,
CreateProfileRechargeOrderResponse,
ProfileMembershipPlan,
ProfileMembershipUpgradeQuote,
ProfileRechargeCenterResponse,
ProfileReferralInviteCenterResponse,
ProfileWalletLedgerResponse,
@@ -41,6 +43,15 @@ export function getClientProfileWalletLedger() {
);
}
export function getClientProfileMembershipUpgradeQuote(
targetPlan: ProfileMembershipPlan,
) {
return invokeAccount<ProfileMembershipUpgradeQuote>(
'read_profile_membership_upgrade_quote',
{ targetPlan },
);
}
export type ClientProfileReferralInviteCenterResponse = {
center: ProfileReferralInviteCenterResponse;
inviteUrl: string;
@@ -26,6 +26,7 @@ vi.mock('../src/services/platformSession', () => ({
import {
confirmClientWechatProfileRechargeOrder,
createClientProfileRechargeOrder,
getClientProfileMembershipUpgradeQuote,
getClientProfileRechargeCenter,
getClientProfileReferralInviteCenter,
getClientProfileWalletLedger,
@@ -49,6 +50,7 @@ test('账户读取只提交结构化参数,不携带 token 或远端地址', a
await getClientProfileRechargeCenter();
await getClientProfileWalletLedger();
await getClientProfileReferralInviteCenter();
await getClientProfileMembershipUpgradeQuote('pro');
await createClientProfileRechargeOrder('product-1');
await confirmClientWechatProfileRechargeOrder('order-1');
await redeemClientProfileRewardCode('CODE-1');
@@ -57,6 +59,7 @@ test('账户读取只提交结构化参数,不携带 token 或远端地址', a
['read_profile_recharge_center', undefined],
['read_profile_wallet_ledger', undefined],
['read_profile_referral_invite_center', undefined],
['read_profile_membership_upgrade_quote', { targetPlan: 'pro' }],
['create_profile_recharge_order', { productId: 'product-1' }],
['confirm_wechat_profile_recharge_order', { orderId: 'order-1' }],
['redeem_profile_reward_code', { code: 'CODE-1' }],