update pay function

This commit is contained in:
2025-11-19 23:41:45 +08:00
parent 683e261756
commit f515dc94f4

View File

@@ -53,6 +53,7 @@ export default function SubscriptionContentNew() {
const [selectedCycle, setSelectedCycle] = useState('yearly'); const [selectedCycle, setSelectedCycle] = useState('yearly');
const [selectedPlan, setSelectedPlan] = useState(null); const [selectedPlan, setSelectedPlan] = useState(null);
const [subscriptionPlans, setSubscriptionPlans] = useState([]);
const [priceInfo, setPriceInfo] = useState(null); const [priceInfo, setPriceInfo] = useState(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [promoCode, setPromoCode] = useState(''); const [promoCode, setPromoCode] = useState('');
@@ -94,6 +95,46 @@ export default function SubscriptionContentNew() {
}; };
}, []); }, []);
// 组件加载时获取套餐数据
useEffect(() => {
fetchSubscriptionPlans();
}, []);
const fetchSubscriptionPlans = async () => {
try {
logger.debug('SubscriptionContentNew', '正在获取订阅套餐');
const response = await fetch('/api/subscription/plans');
if (response.ok) {
const data = await response.json();
if (data.success && Array.isArray(data.data)) {
const validPlans = data.data.filter(
(plan: any) =>
plan &&
plan.name &&
typeof plan.monthly_price === 'number' &&
typeof plan.yearly_price === 'number'
);
logger.debug('SubscriptionContentNew', '套餐加载成功', {
status: response.status,
validPlansCount: validPlans.length,
});
setSubscriptionPlans(validPlans);
} else {
logger.warn('SubscriptionContentNew', '套餐数据格式异常', { data });
setSubscriptionPlans([]);
}
} else {
logger.error('SubscriptionContentNew', 'fetchSubscriptionPlans', new Error(`HTTP ${response.status}`));
setSubscriptionPlans([]);
}
} catch (error) {
logger.error('SubscriptionContentNew', 'fetchSubscriptionPlans', error);
setSubscriptionPlans([]);
}
};
const handlePaymentExpire = () => { const handlePaymentExpire = () => {
stopAutoPaymentCheck(); stopAutoPaymentCheck();
toast({ toast({
@@ -377,13 +418,63 @@ export default function SubscriptionContentNew() {
} }
}; };
// 合并数据库数据和前端配置
const getMergedPlans = () => {
// 如果数据库还没有加载数据,使用静态配置
if (subscriptionPlans.length === 0) {
return subscriptionConfig.plans;
}
// 合并数据库价格和前端UI配置
return subscriptionConfig.plans.map((configPlan: any) => {
const dbPlan = subscriptionPlans.find((p: any) => p.name === configPlan.name);
if (!dbPlan) {
return configPlan; // 如果数据库中没有,使用前端配置
}
// 解析数据库中的 pricing_options JSON
let pricingOptions = configPlan.pricingOptions;
if (dbPlan.pricing_options) {
try {
const parsedOptions = typeof dbPlan.pricing_options === 'string'
? JSON.parse(dbPlan.pricing_options)
: dbPlan.pricing_options;
if (Array.isArray(parsedOptions) && parsedOptions.length > 0) {
pricingOptions = parsedOptions.map((opt: any) => ({
cycleKey: opt.cycle_key,
label: opt.label,
months: opt.months,
price: parseFloat(opt.price),
originalPrice: opt.original_price ? parseFloat(opt.original_price) : null,
discountPercent: opt.discount_percent || 0,
}));
}
} catch (error) {
logger.error('SubscriptionContentNew', '解析pricing_options失败', error);
}
}
// 合并数据,数据库价格优先
return {
...configPlan,
monthly_price: dbPlan.monthly_price,
yearly_price: dbPlan.yearly_price,
pricingOptions: pricingOptions,
displayName: dbPlan.display_name || configPlan.displayName,
description: dbPlan.description || configPlan.description,
};
});
};
const getCurrentPrice = (plan: any) => { const getCurrentPrice = (plan: any) => {
if (!plan || plan.name === 'free') return 0; if (!plan || plan.name === 'free') return 0;
const option = plan.pricingOptions?.find( const option = plan.pricingOptions?.find(
(opt: any) => opt.cycleKey === selectedCycle (opt: any) => opt.cycleKey === selectedCycle
); );
return option ? option.price : plan.pricingOptions[0]?.price || 0; return option ? option.price : plan.pricingOptions?.[0]?.price || 0;
}; };
const getCurrentPriceOption = (plan: any) => { const getCurrentPriceOption = (plan: any) => {
@@ -488,7 +579,7 @@ export default function SubscriptionContentNew() {
flexWrap="wrap" flexWrap="wrap"
justify="center" justify="center"
> >
{subscriptionConfig.plans[1]?.pricingOptions?.map((option: any, index: number) => ( {getMergedPlans()[1]?.pricingOptions?.map((option: any, index: number) => (
<Box key={index} position="relative"> <Box key={index} position="relative">
{option.discountPercent > 0 && ( {option.discountPercent > 0 && (
<Badge <Badge
@@ -534,7 +625,7 @@ export default function SubscriptionContentNew() {
</HStack> </HStack>
{(() => { {(() => {
const currentOption = subscriptionConfig.plans[1]?.pricingOptions?.find( const currentOption = getMergedPlans()[1]?.pricingOptions?.find(
(opt: any) => opt.cycleKey === selectedCycle (opt: any) => opt.cycleKey === selectedCycle
); );
if (currentOption && currentOption.discountPercent > 0) { if (currentOption && currentOption.discountPercent > 0) {
@@ -560,7 +651,7 @@ export default function SubscriptionContentNew() {
maxW="1200px" maxW="1200px"
mx="auto" mx="auto"
> >
{subscriptionConfig.plans.slice(1).map((plan: any, index: number) => { {getMergedPlans().slice(1).map((plan: any, index: number) => {
const IconComponent = getIconComponent(plan.icon); const IconComponent = getIconComponent(plan.icon);
const currentPriceOption = getCurrentPriceOption(plan); const currentPriceOption = getCurrentPriceOption(plan);
const isCurrentPlan = const isCurrentPlan =