update pay function
This commit is contained in:
@@ -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 =
|
||||||
|
|||||||
Reference in New Issue
Block a user