AGC 桌面壳接入会员升级报价与会员下单
- 新增 Tauri 命令 read_profile_membership_upgrade_quote 并注册到桌面端 - accountHost 新增会员升级报价调用 - useAccountWallet 与 AccountWallet 接通报价、会员下单与共享弹层新 props - 补充 accountHost 报价调用测试 Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -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' }],
|
||||
|
||||
Reference in New Issue
Block a user