diff --git a/README.md b/README.md index 8962747..e35728e 100644 --- a/README.md +++ b/README.md @@ -308,6 +308,7 @@ Sub2API **v0.1.88** 及以上版本会自动拼接以下参数,无需手动添 | `user_id` | Sub2API 用户 ID | | `token` | 用户登录 Token(有 token 才能查看订单历史) | | `theme` | `light`(默认)或 `dark` | +| `lang` | 界面语言,`zh`(默认)或 `en` | | `ui_mode` | `standalone`(默认)或 `embedded`(iframe 嵌入) | --- diff --git a/src/app/pay/orders/page.tsx b/src/app/pay/orders/page.tsx index 96afe70..000ca9f 100644 --- a/src/app/pay/orders/page.tsx +++ b/src/app/pay/orders/page.tsx @@ -177,7 +177,7 @@ function OrdersContent() {

{text.missingAuth}

-

{text.visitOrders}

+

{text.visitOrders}

); @@ -238,10 +238,11 @@ function OrdersContent() { function OrdersPageFallback() { const searchParams = useSearchParams(); const locale = resolveLocale(searchParams.get('lang')); + const isDark = searchParams.get('theme') === 'dark'; return ( -
-
{pickLocaleText(locale, '加载中...', 'Loading...')}
+
+
{pickLocaleText(locale, '加载中...', 'Loading...')}
); } diff --git a/src/app/pay/page.tsx b/src/app/pay/page.tsx index d0311ab..fff93ea 100644 --- a/src/app/pay/page.tsx +++ b/src/app/pay/page.tsx @@ -110,7 +110,7 @@ function PayContent() { {pickLocaleText(locale, '帮助', 'Support')}
{helpImageUrl && ( - help setHelpImageOpen(true)} className="mt-3 max-h-40 w-full cursor-zoom-in rounded-lg object-contain bg-white/70 p-2" /> + help setHelpImageOpen(true)} className={`mt-3 max-h-40 w-full cursor-zoom-in rounded-lg object-contain p-2 ${isDark ? 'bg-slate-700/50' : 'bg-white/70'}`} /> )} {helpText && (
@@ -301,7 +301,7 @@ function PayContent() {

{pickLocaleText(locale, '缺少认证信息', 'Missing authentication info')}

-

+

{pickLocaleText(locale, '请从 Sub2API 平台正确访问充值页面', 'Please open the recharge page from the Sub2API platform')}

@@ -314,7 +314,7 @@ function PayContent() {

{pickLocaleText(locale, '用户不存在', 'User not found')}

-

+

{pickLocaleText(locale, '请检查链接是否正确,或联系管理员', 'Please check whether the link is correct or contact the administrator')}

@@ -852,7 +852,7 @@ function PayContent() { {pickLocaleText(locale, '帮助', 'Support')}
{helpImageUrl && ( - help setHelpImageOpen(true)} className="mt-3 max-h-40 w-full cursor-zoom-in rounded-lg object-contain bg-white/70 p-2" /> + help setHelpImageOpen(true)} className={`mt-3 max-h-40 w-full cursor-zoom-in rounded-lg object-contain p-2 ${isDark ? 'bg-slate-700/50' : 'bg-white/70'}`} /> )} {helpText && (
@@ -935,9 +935,10 @@ function PayContent() { function PayPageFallback() { const searchParams = useSearchParams(); const locale = resolveLocale(searchParams.get('lang')); + const isDark = searchParams.get('theme') === 'dark'; return ( -
-
{pickLocaleText(locale, '加载中...', 'Loading...')}
+
+
{pickLocaleText(locale, '加载中...', 'Loading...')}
); } diff --git a/src/app/pay/result/page.tsx b/src/app/pay/result/page.tsx index 8a4c656..1f747e7 100644 --- a/src/app/pay/result/page.tsx +++ b/src/app/pay/result/page.tsx @@ -54,12 +54,12 @@ function closeCurrentWindow() { }, 250); } -function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale, hasAccessToken: boolean) { +function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale, hasAccessToken: boolean, isDark = false) { if (!order) { return locale === 'en' ? { label: 'Payment Error', - color: 'text-red-600', + color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: hasAccessToken ? 'Unable to load the order status. Please try again later.' @@ -67,7 +67,7 @@ function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale } : { label: '支付异常', - color: 'text-red-600', + color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: hasAccessToken ? '未查询到订单状态,请稍后重试。' : '订单访问凭证缺失,请返回原充值页查看订单结果。', }; @@ -77,11 +77,11 @@ function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale return locale === 'en' ? { label: 'Recharge Successful', - color: 'text-green-600', + color: isDark ? 'text-green-400' : 'text-green-600', icon: '✓', message: 'Your balance has been credited successfully.', } - : { label: '充值成功', color: 'text-green-600', icon: '✓', message: '余额已成功到账!' }; + : { label: '充值成功', color: isDark ? 'text-green-400' : 'text-green-600', icon: '✓', message: '余额已成功到账!' }; } if (order.paymentSuccess) { @@ -89,25 +89,25 @@ function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale return locale === 'en' ? { label: 'Top-up Processing', - color: 'text-blue-600', + color: isDark ? 'text-blue-400' : 'text-blue-600', icon: '⟳', message: 'Payment succeeded, and the balance top-up is being processed.', } - : { label: '充值处理中', color: 'text-blue-600', icon: '⟳', message: '支付成功,余额正在充值中...' }; + : { label: '充值处理中', color: isDark ? 'text-blue-400' : 'text-blue-600', icon: '⟳', message: '支付成功,余额正在充值中...' }; } if (order.rechargeStatus === 'failed') { return locale === 'en' ? { label: 'Payment Successful', - color: 'text-amber-600', + color: isDark ? 'text-amber-400' : 'text-amber-600', icon: '!', message: 'Payment succeeded, but the balance top-up has not completed yet. Please check again later or contact the administrator.', } : { label: '支付成功', - color: 'text-amber-600', + color: isDark ? 'text-amber-400' : 'text-amber-600', icon: '!', message: '支付成功,但余额充值暂未完成,请稍后查看订单结果或联系管理员。', }; @@ -116,30 +116,30 @@ function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale if (order.status === 'PENDING') { return locale === 'en' - ? { label: 'Awaiting Payment', color: 'text-yellow-600', icon: '⏳', message: 'The order has not been paid yet.' } - : { label: '等待支付', color: 'text-yellow-600', icon: '⏳', message: '订单尚未完成支付。' }; + ? { label: 'Awaiting Payment', color: isDark ? 'text-yellow-400' : 'text-yellow-600', icon: '⏳', message: 'The order has not been paid yet.' } + : { label: '等待支付', color: isDark ? 'text-yellow-400' : 'text-yellow-600', icon: '⏳', message: '订单尚未完成支付。' }; } if (order.status === 'EXPIRED') { return locale === 'en' ? { label: 'Order Expired', - color: 'text-gray-500', + color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '⏰', message: 'This order has expired. Please create a new order.', } - : { label: '订单已超时', color: 'text-gray-500', icon: '⏰', message: '订单已超时,请重新充值。' }; + : { label: '订单已超时', color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '⏰', message: '订单已超时,请重新充值。' }; } if (order.status === 'CANCELLED') { return locale === 'en' - ? { label: 'Order Cancelled', color: 'text-gray-500', icon: '✗', message: 'This order has been cancelled.' } - : { label: '订单已取消', color: 'text-gray-500', icon: '✗', message: '订单已被取消。' }; + ? { label: 'Order Cancelled', color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '✗', message: 'This order has been cancelled.' } + : { label: '订单已取消', color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '✗', message: '订单已被取消。' }; } return locale === 'en' - ? { label: 'Payment Error', color: 'text-red-600', icon: '✗', message: 'Please contact the administrator.' } - : { label: '支付异常', color: 'text-red-600', icon: '✗', message: '请联系管理员处理。' }; + ? { label: 'Payment Error', color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: 'Please contact the administrator.' } + : { label: '支付异常', color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: '请联系管理员处理。' }; } function ResultContent() { @@ -233,7 +233,7 @@ function ResultContent() { ); } - const display = getStatusConfig(orderState, locale, Boolean(accessToken)); + const display = getStatusConfig(orderState, locale, Boolean(accessToken), isDark); return (
@@ -254,14 +254,14 @@ function ResultContent() {
) ) : ( - )} @@ -277,10 +277,11 @@ function ResultContent() { function ResultPageFallback() { const searchParams = useSearchParams(); const locale = resolveLocale(searchParams.get('lang')); + const isDark = searchParams.get('theme') === 'dark'; return ( -
-
{pickLocaleText(locale, '加载中...', 'Loading...')}
+
+
{pickLocaleText(locale, '加载中...', 'Loading...')}
); } diff --git a/src/app/pay/stripe-popup/page.tsx b/src/app/pay/stripe-popup/page.tsx index 0efd5c4..a1f6b02 100644 --- a/src/app/pay/stripe-popup/page.tsx +++ b/src/app/pay/stripe-popup/page.tsx @@ -195,7 +195,7 @@ function StripePopupContent() { className={`w-full max-w-md space-y-4 rounded-2xl border p-6 ${isDark ? 'border-slate-700 bg-slate-900' : 'border-slate-200 bg-white'} shadow-lg`} >
-
+
{'¥'} {amount.toFixed(2)}
@@ -213,7 +213,7 @@ function StripePopupContent() { @@ -235,7 +235,7 @@ function StripePopupContent() { className={`w-full max-w-md space-y-4 rounded-2xl border p-6 ${isDark ? 'border-slate-700 bg-slate-900' : 'border-slate-200 bg-white'} shadow-lg`} >
-
+
{'¥'} {amount.toFixed(2)}
@@ -251,12 +251,12 @@ function StripePopupContent() {
) : stripeSuccess ? (
-
{'✓'}
+
{'✓'}

{text.successClosing}

@@ -280,7 +280,9 @@ function StripePopupContent() { onClick={handleSubmit} className={[ 'w-full rounded-lg py-3 font-medium text-white shadow-md transition-colors', - stripeSubmitting ? 'bg-gray-400 cursor-not-allowed' : getPaymentMeta('stripe').buttonClass, + stripeSubmitting + ? isDark ? 'bg-slate-700 text-slate-400 cursor-not-allowed' : 'bg-gray-400 cursor-not-allowed' + : getPaymentMeta('stripe').buttonClass, ].join(' ')} > {stripeSubmitting ? ( @@ -302,10 +304,11 @@ function StripePopupContent() { function StripePopupFallback() { const searchParams = useSearchParams(); const locale = resolveLocale(searchParams.get('lang')); + const isDark = searchParams.get('theme') === 'dark'; return ( -
-
{pickLocaleText(locale, '加载中...', 'Loading...')}
+
+
{pickLocaleText(locale, '加载中...', 'Loading...')}
); } diff --git a/src/components/MobileOrderList.tsx b/src/components/MobileOrderList.tsx index f74bbf7..ecb90e0 100644 --- a/src/components/MobileOrderList.tsx +++ b/src/components/MobileOrderList.tsx @@ -134,7 +134,7 @@ export default function MobileOrderList({ {locale === 'en' ? 'Loading...' : '加载中...'} ) : ( - + {locale === 'en' ? 'Scroll up to load more' : '上滑加载更多'} )} @@ -142,7 +142,7 @@ export default function MobileOrderList({ )} {!hasMore && orders.length > 0 && ( -
+
{locale === 'en' ? 'All orders loaded' : '已显示全部订单'}
)} diff --git a/src/components/OrderStatus.tsx b/src/components/OrderStatus.tsx index b16c773..04eaab2 100644 --- a/src/components/OrderStatus.tsx +++ b/src/components/OrderStatus.tsx @@ -15,16 +15,16 @@ interface OrderStatusProps { locale?: Locale; } -function getStatusConfig(order: PublicOrderStatusSnapshot, locale: Locale) { +function getStatusConfig(order: PublicOrderStatusSnapshot, locale: Locale, isDark = false) { if (order.rechargeSuccess) { return locale === 'en' ? { label: 'Recharge Successful', - color: 'text-green-600', + color: isDark ? 'text-green-400' : 'text-green-600', icon: '✓', message: 'Your balance has been credited. Thank you for your payment.', } - : { label: '充值成功', color: 'text-green-600', icon: '✓', message: '余额已到账,感谢您的充值!' }; + : { label: '充值成功', color: isDark ? 'text-green-400' : 'text-green-600', icon: '✓', message: '余额已到账,感谢您的充值!' }; } if (order.paymentSuccess) { @@ -32,25 +32,25 @@ function getStatusConfig(order: PublicOrderStatusSnapshot, locale: Locale) { return locale === 'en' ? { label: 'Recharging', - color: 'text-blue-600', + color: isDark ? 'text-blue-400' : 'text-blue-600', icon: '⟳', message: 'Payment received. Recharging your balance...', } - : { label: '充值中', color: 'text-blue-600', icon: '⟳', message: '支付成功,正在充值余额中,请稍候...' }; + : { label: '充值中', color: isDark ? 'text-blue-400' : 'text-blue-600', icon: '⟳', message: '支付成功,正在充值余额中,请稍候...' }; } if (order.rechargeStatus === 'failed') { return locale === 'en' ? { label: 'Payment Successful', - color: 'text-amber-600', + color: isDark ? 'text-amber-400' : 'text-amber-600', icon: '!', message: 'Payment completed, but the balance top-up has not finished yet. The system may retry automatically. Please check the order list later or contact the administrator if it remains unresolved.', } : { label: '支付成功', - color: 'text-amber-600', + color: isDark ? 'text-amber-400' : 'text-amber-600', icon: '!', message: '支付已完成,但余额充值暂未完成。系统可能会自动重试,请稍后在订单列表查看;如长时间未到账请联系管理员。', @@ -62,14 +62,14 @@ function getStatusConfig(order: PublicOrderStatusSnapshot, locale: Locale) { return locale === 'en' ? { label: 'Payment Failed', - color: 'text-red-600', + color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: 'Payment was not completed. Please try again. If funds were deducted but not credited, contact the administrator.', } : { label: '支付失败', - color: 'text-red-600', + color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: '支付未完成,请重新发起支付;如已扣款未到账,请联系管理员处理。', }; @@ -77,35 +77,35 @@ function getStatusConfig(order: PublicOrderStatusSnapshot, locale: Locale) { if (order.status === 'PENDING') { return locale === 'en' - ? { label: 'Awaiting Payment', color: 'text-yellow-600', icon: '⏳', message: 'The order has not been paid yet.' } - : { label: '等待支付', color: 'text-yellow-600', icon: '⏳', message: '订单尚未完成支付。' }; + ? { label: 'Awaiting Payment', color: isDark ? 'text-yellow-400' : 'text-yellow-600', icon: '⏳', message: 'The order has not been paid yet.' } + : { label: '等待支付', color: isDark ? 'text-yellow-400' : 'text-yellow-600', icon: '⏳', message: '订单尚未完成支付。' }; } if (order.status === 'EXPIRED') { return locale === 'en' ? { label: 'Order Expired', - color: 'text-gray-500', + color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '⏰', message: 'This order has expired. Please create a new one.', } - : { label: '订单超时', color: 'text-gray-500', icon: '⏰', message: '订单已超时,请重新创建订单。' }; + : { label: '订单超时', color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '⏰', message: '订单已超时,请重新创建订单。' }; } if (order.status === 'CANCELLED') { return locale === 'en' - ? { label: 'Cancelled', color: 'text-gray-500', icon: '✗', message: 'The order has been cancelled.' } - : { label: '已取消', color: 'text-gray-500', icon: '✗', message: '订单已取消。' }; + ? { label: 'Cancelled', color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '✗', message: 'The order has been cancelled.' } + : { label: '已取消', color: isDark ? 'text-slate-400' : 'text-gray-500', icon: '✗', message: '订单已取消。' }; } return locale === 'en' ? { label: 'Payment Error', - color: 'text-red-600', + color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: 'Payment status is abnormal. Please contact the administrator.', } - : { label: '支付异常', color: 'text-red-600', icon: '✗', message: '支付状态异常,请联系管理员处理。' }; + : { label: '支付异常', color: isDark ? 'text-red-400' : 'text-red-600', icon: '✗', message: '支付状态异常,请联系管理员处理。' }; } export default function OrderStatus({ @@ -156,7 +156,7 @@ export default function OrderStatus({ }; }, [orderId, currentOrder.paymentSuccess, currentOrder.rechargeSuccess, statusAccessToken]); - const config = getStatusConfig(currentOrder, locale); + const config = getStatusConfig(currentOrder, locale, dark); const doneLabel = locale === 'en' ? 'Done' : '完成'; const backLabel = locale === 'en' ? 'Back to Recharge' : '返回充值'; diff --git a/src/components/PaymentForm.tsx b/src/components/PaymentForm.tsx index 1ec0d18..bc6b1bd 100644 --- a/src/components/PaymentForm.tsx +++ b/src/components/PaymentForm.tsx @@ -195,7 +195,9 @@ export default function PaymentForm({ onClick={() => handleQuickAmount(val)} className={`rounded-lg border-2 px-4 py-3 text-center font-medium transition-colors ${ amount === val - ? 'border-blue-500 bg-blue-50 text-blue-700' + ? dark + ? 'border-blue-500 bg-blue-900/40 text-blue-300' + : 'border-blue-500 bg-blue-50 text-blue-700' : dark ? 'border-slate-700 bg-slate-900 text-slate-200 hover:border-slate-500' : 'border-gray-200 bg-white text-gray-700 hover:border-gray-300' @@ -373,12 +375,12 @@ export default function PaymentForm({ @@ -409,7 +412,7 @@ export default function PaymentQRCode({ return (
-
+
{'¥'} {displayAmount.toFixed(2)}
@@ -465,13 +468,16 @@ export default function PaymentQRCode({ ].join(' ')} /> {stripeError && ( -
+
{stripeError}
)} {stripeSuccess ? (
-
{'✓'}
+
{'✓'}

{t.successProcessing}