style: 统一代码格式 (prettier)
This commit is contained in:
@@ -39,33 +39,34 @@ function DashboardContent() {
|
||||
const isDark = theme === 'dark';
|
||||
const isEmbedded = uiMode === 'embedded';
|
||||
|
||||
const text = locale === 'en'
|
||||
? {
|
||||
missingToken: 'Missing admin token',
|
||||
missingTokenHint: 'Please access the admin page from the Sub2API platform.',
|
||||
invalidToken: 'Invalid admin token',
|
||||
requestFailed: 'Request failed',
|
||||
loadFailed: 'Failed to load data',
|
||||
title: 'Dashboard',
|
||||
subtitle: 'Recharge order analytics and insights',
|
||||
daySuffix: 'd',
|
||||
orders: 'Order Management',
|
||||
refresh: 'Refresh',
|
||||
loading: 'Loading...',
|
||||
}
|
||||
: {
|
||||
missingToken: '缺少管理员凭证',
|
||||
missingTokenHint: '请从 Sub2API 平台正确访问管理页面',
|
||||
invalidToken: '管理员凭证无效',
|
||||
requestFailed: '请求失败',
|
||||
loadFailed: '加载数据失败',
|
||||
title: '数据概览',
|
||||
subtitle: '充值订单统计与分析',
|
||||
daySuffix: '天',
|
||||
orders: '订单管理',
|
||||
refresh: '刷新',
|
||||
loading: '加载中...',
|
||||
};
|
||||
const text =
|
||||
locale === 'en'
|
||||
? {
|
||||
missingToken: 'Missing admin token',
|
||||
missingTokenHint: 'Please access the admin page from the Sub2API platform.',
|
||||
invalidToken: 'Invalid admin token',
|
||||
requestFailed: 'Request failed',
|
||||
loadFailed: 'Failed to load data',
|
||||
title: 'Dashboard',
|
||||
subtitle: 'Recharge order analytics and insights',
|
||||
daySuffix: 'd',
|
||||
orders: 'Order Management',
|
||||
refresh: 'Refresh',
|
||||
loading: 'Loading...',
|
||||
}
|
||||
: {
|
||||
missingToken: '缺少管理员凭证',
|
||||
missingTokenHint: '请从 Sub2API 平台正确访问管理页面',
|
||||
invalidToken: '管理员凭证无效',
|
||||
requestFailed: '请求失败',
|
||||
loadFailed: '加载数据失败',
|
||||
title: '数据概览',
|
||||
subtitle: '充值订单统计与分析',
|
||||
daySuffix: '天',
|
||||
orders: '订单管理',
|
||||
refresh: '刷新',
|
||||
loading: '加载中...',
|
||||
};
|
||||
|
||||
const [days, setDays] = useState<number>(30);
|
||||
const [data, setData] = useState<DashboardData | null>(null);
|
||||
@@ -138,7 +139,8 @@ function DashboardContent() {
|
||||
<>
|
||||
{DAYS_OPTIONS.map((d) => (
|
||||
<button key={d} type="button" onClick={() => setDays(d)} className={days === d ? btnActive : btnBase}>
|
||||
{d}{text.daySuffix}
|
||||
{d}
|
||||
{text.daySuffix}
|
||||
</button>
|
||||
))}
|
||||
<a href={`/admin?${navParams}`} className={btnBase}>
|
||||
@@ -162,7 +164,7 @@ function DashboardContent() {
|
||||
)}
|
||||
|
||||
{loading ? (
|
||||
<div className={`py-24 text-center ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{text.loading}</div>
|
||||
<div className={`py-24 text-center ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{text.loading}</div>
|
||||
) : data ? (
|
||||
<div className="space-y-6">
|
||||
<DashboardStats summary={data.summary} dark={isDark} locale={locale} />
|
||||
@@ -190,9 +192,7 @@ function DashboardPageFallback() {
|
||||
|
||||
export default function DashboardPage() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={<DashboardPageFallback />}
|
||||
>
|
||||
<Suspense fallback={<DashboardPageFallback />}>
|
||||
<DashboardContent />
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
@@ -52,67 +52,68 @@ function AdminContent() {
|
||||
const isDark = theme === 'dark';
|
||||
const isEmbedded = uiMode === 'embedded';
|
||||
|
||||
const text = locale === 'en'
|
||||
? {
|
||||
missingToken: 'Missing admin token',
|
||||
missingTokenHint: 'Please access the admin page from the Sub2API platform.',
|
||||
invalidToken: 'Invalid admin token',
|
||||
requestFailed: 'Request failed',
|
||||
loadOrdersFailed: 'Failed to load orders',
|
||||
retryConfirm: 'Retry recharge for this order?',
|
||||
retryFailed: 'Retry failed',
|
||||
retryRequestFailed: 'Retry request failed',
|
||||
cancelConfirm: 'Cancel this order?',
|
||||
cancelFailed: 'Cancel failed',
|
||||
cancelRequestFailed: 'Cancel request failed',
|
||||
loadDetailFailed: 'Failed to load order details',
|
||||
title: 'Order Management',
|
||||
subtitle: 'View and manage all recharge orders',
|
||||
dashboard: 'Dashboard',
|
||||
refresh: 'Refresh',
|
||||
loading: 'Loading...',
|
||||
statuses: {
|
||||
'': 'All',
|
||||
PENDING: 'Pending',
|
||||
PAID: 'Paid',
|
||||
RECHARGING: 'Recharging',
|
||||
COMPLETED: 'Completed',
|
||||
EXPIRED: 'Expired',
|
||||
CANCELLED: 'Cancelled',
|
||||
FAILED: 'Recharge failed',
|
||||
REFUNDED: 'Refunded',
|
||||
},
|
||||
}
|
||||
: {
|
||||
missingToken: '缺少管理员凭证',
|
||||
missingTokenHint: '请从 Sub2API 平台正确访问管理页面',
|
||||
invalidToken: '管理员凭证无效',
|
||||
requestFailed: '请求失败',
|
||||
loadOrdersFailed: '加载订单列表失败',
|
||||
retryConfirm: '确认重试充值?',
|
||||
retryFailed: '重试失败',
|
||||
retryRequestFailed: '重试请求失败',
|
||||
cancelConfirm: '确认取消该订单?',
|
||||
cancelFailed: '取消失败',
|
||||
cancelRequestFailed: '取消请求失败',
|
||||
loadDetailFailed: '加载订单详情失败',
|
||||
title: '订单管理',
|
||||
subtitle: '查看和管理所有充值订单',
|
||||
dashboard: '数据概览',
|
||||
refresh: '刷新',
|
||||
loading: '加载中...',
|
||||
statuses: {
|
||||
'': '全部',
|
||||
PENDING: '待支付',
|
||||
PAID: '已支付',
|
||||
RECHARGING: '充值中',
|
||||
COMPLETED: '已完成',
|
||||
EXPIRED: '已超时',
|
||||
CANCELLED: '已取消',
|
||||
FAILED: '充值失败',
|
||||
REFUNDED: '已退款',
|
||||
},
|
||||
};
|
||||
const text =
|
||||
locale === 'en'
|
||||
? {
|
||||
missingToken: 'Missing admin token',
|
||||
missingTokenHint: 'Please access the admin page from the Sub2API platform.',
|
||||
invalidToken: 'Invalid admin token',
|
||||
requestFailed: 'Request failed',
|
||||
loadOrdersFailed: 'Failed to load orders',
|
||||
retryConfirm: 'Retry recharge for this order?',
|
||||
retryFailed: 'Retry failed',
|
||||
retryRequestFailed: 'Retry request failed',
|
||||
cancelConfirm: 'Cancel this order?',
|
||||
cancelFailed: 'Cancel failed',
|
||||
cancelRequestFailed: 'Cancel request failed',
|
||||
loadDetailFailed: 'Failed to load order details',
|
||||
title: 'Order Management',
|
||||
subtitle: 'View and manage all recharge orders',
|
||||
dashboard: 'Dashboard',
|
||||
refresh: 'Refresh',
|
||||
loading: 'Loading...',
|
||||
statuses: {
|
||||
'': 'All',
|
||||
PENDING: 'Pending',
|
||||
PAID: 'Paid',
|
||||
RECHARGING: 'Recharging',
|
||||
COMPLETED: 'Completed',
|
||||
EXPIRED: 'Expired',
|
||||
CANCELLED: 'Cancelled',
|
||||
FAILED: 'Recharge failed',
|
||||
REFUNDED: 'Refunded',
|
||||
},
|
||||
}
|
||||
: {
|
||||
missingToken: '缺少管理员凭证',
|
||||
missingTokenHint: '请从 Sub2API 平台正确访问管理页面',
|
||||
invalidToken: '管理员凭证无效',
|
||||
requestFailed: '请求失败',
|
||||
loadOrdersFailed: '加载订单列表失败',
|
||||
retryConfirm: '确认重试充值?',
|
||||
retryFailed: '重试失败',
|
||||
retryRequestFailed: '重试请求失败',
|
||||
cancelConfirm: '确认取消该订单?',
|
||||
cancelFailed: '取消失败',
|
||||
cancelRequestFailed: '取消请求失败',
|
||||
loadDetailFailed: '加载订单详情失败',
|
||||
title: '订单管理',
|
||||
subtitle: '查看和管理所有充值订单',
|
||||
dashboard: '数据概览',
|
||||
refresh: '刷新',
|
||||
loading: '加载中...',
|
||||
statuses: {
|
||||
'': '全部',
|
||||
PENDING: '待支付',
|
||||
PAID: '已支付',
|
||||
RECHARGING: '充值中',
|
||||
COMPLETED: '已完成',
|
||||
EXPIRED: '已超时',
|
||||
CANCELLED: '已取消',
|
||||
FAILED: '充值失败',
|
||||
REFUNDED: '已退款',
|
||||
},
|
||||
};
|
||||
|
||||
const [orders, setOrders] = useState<AdminOrder[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
@@ -321,7 +322,9 @@ function AdminContent() {
|
||||
/>
|
||||
|
||||
{/* Order Detail */}
|
||||
{detailOrder && <OrderDetail order={detailOrder} onClose={() => setDetailOrder(null)} dark={isDark} locale={locale} />}
|
||||
{detailOrder && (
|
||||
<OrderDetail order={detailOrder} onClose={() => setDetailOrder(null)} dark={isDark} locale={locale} />
|
||||
)}
|
||||
</PayPageLayout>
|
||||
);
|
||||
}
|
||||
@@ -339,9 +342,7 @@ function AdminPageFallback() {
|
||||
|
||||
export default function AdminPage() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={<AdminPageFallback />}
|
||||
>
|
||||
<Suspense fallback={<AdminPageFallback />}>
|
||||
<AdminContent />
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,10 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
const token = request.nextUrl.searchParams.get('token')?.trim();
|
||||
if (!token) {
|
||||
return NextResponse.json({ error: locale === 'en' ? 'Missing token parameter' : '缺少 token 参数' }, { status: 401 });
|
||||
return NextResponse.json(
|
||||
{ error: locale === 'en' ? 'Missing token parameter' : '缺少 token 参数' },
|
||||
{ status: 401 },
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -28,7 +31,10 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
if (tokenUser.id !== userId) {
|
||||
return NextResponse.json({ error: locale === 'en' ? 'Forbidden to access this user' : '无权访问该用户信息' }, { status: 403 });
|
||||
return NextResponse.json(
|
||||
{ error: locale === 'en' ? 'Forbidden to access this user' : '无权访问该用户信息' },
|
||||
{ status: 403 },
|
||||
);
|
||||
}
|
||||
|
||||
const env = getEnv();
|
||||
@@ -77,9 +83,7 @@ export async function GET(request: NextRequest) {
|
||||
helpImageUrl: env.PAY_HELP_IMAGE_URL ?? null,
|
||||
helpText: env.PAY_HELP_TEXT ?? null,
|
||||
stripePublishableKey:
|
||||
enabledTypes.includes('stripe') && env.STRIPE_PUBLISHABLE_KEY
|
||||
? env.STRIPE_PUBLISHABLE_KEY
|
||||
: null,
|
||||
enabledTypes.includes('stripe') && env.STRIPE_PUBLISHABLE_KEY ? env.STRIPE_PUBLISHABLE_KEY : null,
|
||||
sublabelOverrides: Object.keys(sublabelOverrides).length > 0 ? sublabelOverrides : null,
|
||||
},
|
||||
});
|
||||
@@ -89,6 +93,9 @@ export async function GET(request: NextRequest) {
|
||||
return NextResponse.json({ error: locale === 'en' ? 'User not found' : '用户不存在' }, { status: 404 });
|
||||
}
|
||||
console.error('Get user error:', error);
|
||||
return NextResponse.json({ error: locale === 'en' ? 'Failed to fetch user info' : '获取用户信息失败' }, { status: 500 });
|
||||
return NextResponse.json(
|
||||
{ error: locale === 'en' ? 'Failed to fetch user info' : '获取用户信息失败' },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,15 +22,11 @@ export async function POST(request: NextRequest) {
|
||||
return Response.json({ code: 'SUCCESS', message: '成功' });
|
||||
}
|
||||
const success = await handlePaymentNotify(notification, provider.name);
|
||||
return Response.json(
|
||||
success ? { code: 'SUCCESS', message: '成功' } : { code: 'FAIL', message: '处理失败' },
|
||||
{ status: success ? 200 : 500 },
|
||||
);
|
||||
return Response.json(success ? { code: 'SUCCESS', message: '成功' } : { code: 'FAIL', message: '处理失败' }, {
|
||||
status: success ? 200 : 500,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Wxpay notify error:', error);
|
||||
return Response.json(
|
||||
{ code: 'FAIL', message: '处理失败' },
|
||||
{ status: 500 },
|
||||
);
|
||||
return Response.json({ code: 'FAIL', message: '处理失败' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,11 @@
|
||||
body {
|
||||
background: var(--background);
|
||||
color: var(--foreground);
|
||||
font-family: system-ui, -apple-system, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||
font-family:
|
||||
system-ui,
|
||||
-apple-system,
|
||||
'PingFang SC',
|
||||
'Hiragino Sans GB',
|
||||
'Microsoft YaHei',
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,16 @@ function OrdersContent() {
|
||||
|
||||
const text = {
|
||||
missingAuth: pickLocaleText(locale, '缺少认证信息', 'Missing authentication information'),
|
||||
visitOrders: pickLocaleText(locale, '请从 Sub2API 平台正确访问订单页面', 'Please open the orders page from Sub2API'),
|
||||
sessionExpired: pickLocaleText(locale, '登录态已失效,请从 Sub2API 重新进入支付页。', 'Session expired. Please re-enter from Sub2API.'),
|
||||
visitOrders: pickLocaleText(
|
||||
locale,
|
||||
'请从 Sub2API 平台正确访问订单页面',
|
||||
'Please open the orders page from Sub2API',
|
||||
),
|
||||
sessionExpired: pickLocaleText(
|
||||
locale,
|
||||
'登录态已失效,请从 Sub2API 重新进入支付页。',
|
||||
'Session expired. Please re-enter from Sub2API.',
|
||||
),
|
||||
loadFailed: pickLocaleText(locale, '订单加载失败,请稍后重试。', 'Failed to load orders. Please try again later.'),
|
||||
networkError: pickLocaleText(locale, '网络错误,请稍后重试。', 'Network error. Please try again later.'),
|
||||
switchingMobileTab: pickLocaleText(locale, '正在切换到移动端订单 Tab...', 'Switching to mobile orders tab...'),
|
||||
@@ -40,7 +48,11 @@ function OrdersContent() {
|
||||
backToPay: pickLocaleText(locale, '返回充值', 'Back to Top Up'),
|
||||
loading: pickLocaleText(locale, '加载中...', 'Loading...'),
|
||||
userPrefix: pickLocaleText(locale, '用户', 'User'),
|
||||
authError: pickLocaleText(locale, '缺少认证信息,请从 Sub2API 平台正确访问订单页面', 'Missing authentication information. Please open the orders page from Sub2API.'),
|
||||
authError: pickLocaleText(
|
||||
locale,
|
||||
'缺少认证信息,请从 Sub2API 平台正确访问订单页面',
|
||||
'Missing authentication information. Please open the orders page from Sub2API.',
|
||||
),
|
||||
};
|
||||
|
||||
const [isIframeContext, setIsIframeContext] = useState(true);
|
||||
|
||||
@@ -156,8 +156,7 @@ function PayContent() {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
|
||||
const loadMoreOrders = async () => {
|
||||
@@ -203,7 +202,11 @@ function PayContent() {
|
||||
<div className="text-center text-red-500">
|
||||
<p className="text-lg font-medium">{pickLocaleText(locale, '缺少认证信息', 'Missing authentication info')}</p>
|
||||
<p className="mt-2 text-sm text-gray-500">
|
||||
{pickLocaleText(locale, '请从 Sub2API 平台正确访问充值页面', 'Please open the recharge page from the Sub2API platform')}
|
||||
{pickLocaleText(
|
||||
locale,
|
||||
'请从 Sub2API 平台正确访问充值页面',
|
||||
'Please open the recharge page from the Sub2API platform',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,7 +219,11 @@ function PayContent() {
|
||||
<div className="text-center text-red-500">
|
||||
<p className="text-lg font-medium">{pickLocaleText(locale, '用户不存在', 'User not found')}</p>
|
||||
<p className="mt-2 text-sm text-gray-500">
|
||||
{pickLocaleText(locale, '请检查链接是否正确,或联系管理员', 'Please check whether the link is correct or contact the administrator')}
|
||||
{pickLocaleText(
|
||||
locale,
|
||||
'请检查链接是否正确,或联系管理员',
|
||||
'Please check whether the link is correct or contact the administrator',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -272,15 +279,33 @@ function PayContent() {
|
||||
|
||||
if (!res.ok) {
|
||||
const codeMessages: Record<string, string> = {
|
||||
INVALID_TOKEN: pickLocaleText(locale, '认证已失效,请重新从平台进入充值页面', 'Authentication expired. Please re-enter the recharge page from the platform'),
|
||||
USER_INACTIVE: pickLocaleText(locale, '账户已被禁用,无法充值,请联系管理员', 'This account is disabled and cannot be recharged. Please contact the administrator'),
|
||||
TOO_MANY_PENDING: pickLocaleText(locale, '您有过多待支付订单,请先完成或取消现有订单后再试', 'You have too many pending orders. Please complete or cancel existing orders first'),
|
||||
USER_NOT_FOUND: pickLocaleText(locale, '用户不存在,请检查链接是否正确', 'User not found. Please check whether the link is correct'),
|
||||
INVALID_TOKEN: pickLocaleText(
|
||||
locale,
|
||||
'认证已失效,请重新从平台进入充值页面',
|
||||
'Authentication expired. Please re-enter the recharge page from the platform',
|
||||
),
|
||||
USER_INACTIVE: pickLocaleText(
|
||||
locale,
|
||||
'账户已被禁用,无法充值,请联系管理员',
|
||||
'This account is disabled and cannot be recharged. Please contact the administrator',
|
||||
),
|
||||
TOO_MANY_PENDING: pickLocaleText(
|
||||
locale,
|
||||
'您有过多待支付订单,请先完成或取消现有订单后再试',
|
||||
'You have too many pending orders. Please complete or cancel existing orders first',
|
||||
),
|
||||
USER_NOT_FOUND: pickLocaleText(
|
||||
locale,
|
||||
'用户不存在,请检查链接是否正确',
|
||||
'User not found. Please check whether the link is correct',
|
||||
),
|
||||
DAILY_LIMIT_EXCEEDED: data.error,
|
||||
METHOD_DAILY_LIMIT_EXCEEDED: data.error,
|
||||
PAYMENT_GATEWAY_ERROR: data.error,
|
||||
};
|
||||
setError(codeMessages[data.code] || data.error || pickLocaleText(locale, '创建订单失败', 'Failed to create order'));
|
||||
setError(
|
||||
codeMessages[data.code] || data.error || pickLocaleText(locale, '创建订单失败', 'Failed to create order'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -481,11 +506,24 @@ function PayContent() {
|
||||
{pickLocaleText(locale, '支付说明', 'Payment Notes')}
|
||||
</div>
|
||||
<ul className={['mt-2 space-y-1 text-sm', isDark ? 'text-slate-300' : 'text-slate-600'].join(' ')}>
|
||||
<li>{pickLocaleText(locale, '订单完成后会自动到账', 'Balance will be credited automatically after the order completes')}</li>
|
||||
<li>{pickLocaleText(locale, '如需历史记录请查看「我的订单」', 'Check "My Orders" for payment history')}</li>
|
||||
<li>
|
||||
{pickLocaleText(
|
||||
locale,
|
||||
'订单完成后会自动到账',
|
||||
'Balance will be credited automatically after the order completes',
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{pickLocaleText(
|
||||
locale,
|
||||
'如需历史记录请查看「我的订单」',
|
||||
'Check "My Orders" for payment history',
|
||||
)}
|
||||
</li>
|
||||
{config.maxDailyAmount > 0 && (
|
||||
<li>
|
||||
{pickLocaleText(locale, '每日最大充值', 'Maximum daily recharge')} ¥{config.maxDailyAmount.toFixed(2)}
|
||||
{pickLocaleText(locale, '每日最大充值', 'Maximum daily recharge')} ¥
|
||||
{config.maxDailyAmount.toFixed(2)}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
@@ -551,18 +589,17 @@ function PayContent() {
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
{step === 'result' && orderResult && finalOrderState && (
|
||||
<OrderStatus
|
||||
orderId={orderResult.orderId}
|
||||
order={finalOrderState}
|
||||
statusAccessToken={orderResult.statusAccessToken}
|
||||
onStateChange={setFinalOrderState}
|
||||
onBack={handleBack}
|
||||
dark={isDark}
|
||||
locale={locale}
|
||||
/>
|
||||
)}
|
||||
{step === 'result' && orderResult && finalOrderState && (
|
||||
<OrderStatus
|
||||
orderId={orderResult.orderId}
|
||||
order={finalOrderState}
|
||||
statusAccessToken={orderResult.statusAccessToken}
|
||||
onStateChange={setFinalOrderState}
|
||||
onBack={handleBack}
|
||||
dark={isDark}
|
||||
locale={locale}
|
||||
/>
|
||||
)}
|
||||
|
||||
{helpImageOpen && helpImageUrl && (
|
||||
<div
|
||||
@@ -594,9 +631,7 @@ function PayPageFallback() {
|
||||
|
||||
export default function PayPage() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={<PayPageFallback />}
|
||||
>
|
||||
<Suspense fallback={<PayPageFallback />}>
|
||||
<PayContent />
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
'use client';
|
||||
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
@@ -58,27 +57,60 @@ function closeCurrentWindow() {
|
||||
function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale, hasAccessToken: boolean) {
|
||||
if (!order) {
|
||||
return locale === 'en'
|
||||
? { label: 'Payment Error', color: 'text-red-600', icon: '✗', message: hasAccessToken ? 'Unable to load the order status. Please try again later.' : 'Missing order access token. Please go back to the recharge page.' }
|
||||
: { label: '支付异常', color: 'text-red-600', icon: '✗', message: hasAccessToken ? '未查询到订单状态,请稍后重试。' : '订单访问凭证缺失,请返回原充值页查看订单结果。' };
|
||||
? {
|
||||
label: 'Payment Error',
|
||||
color: 'text-red-600',
|
||||
icon: '✗',
|
||||
message: hasAccessToken
|
||||
? 'Unable to load the order status. Please try again later.'
|
||||
: 'Missing order access token. Please go back to the recharge page.',
|
||||
}
|
||||
: {
|
||||
label: '支付异常',
|
||||
color: 'text-red-600',
|
||||
icon: '✗',
|
||||
message: hasAccessToken ? '未查询到订单状态,请稍后重试。' : '订单访问凭证缺失,请返回原充值页查看订单结果。',
|
||||
};
|
||||
}
|
||||
|
||||
if (order.rechargeSuccess) {
|
||||
return locale === 'en'
|
||||
? { label: 'Recharge Successful', color: 'text-green-600', icon: '✓', message: 'Your balance has been credited successfully.' }
|
||||
? {
|
||||
label: 'Recharge Successful',
|
||||
color: 'text-green-600',
|
||||
icon: '✓',
|
||||
message: 'Your balance has been credited successfully.',
|
||||
}
|
||||
: { label: '充值成功', color: 'text-green-600', icon: '✓', message: '余额已成功到账!' };
|
||||
}
|
||||
|
||||
if (order.paymentSuccess) {
|
||||
if (order.rechargeStatus === 'paid_pending' || order.rechargeStatus === 'recharging') {
|
||||
return locale === 'en'
|
||||
? { label: 'Top-up Processing', color: 'text-blue-600', icon: '⟳', message: 'Payment succeeded, and the balance top-up is being processed.' }
|
||||
? {
|
||||
label: 'Top-up Processing',
|
||||
color: 'text-blue-600',
|
||||
icon: '⟳',
|
||||
message: 'Payment succeeded, and the balance top-up is being processed.',
|
||||
}
|
||||
: { label: '充值处理中', color: 'text-blue-600', icon: '⟳', message: '支付成功,余额正在充值中...' };
|
||||
}
|
||||
|
||||
if (order.rechargeStatus === 'failed') {
|
||||
return locale === 'en'
|
||||
? { label: 'Payment Successful', color: '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', icon: '!', message: '支付成功,但余额充值暂未完成,请稍后查看订单结果或联系管理员。' };
|
||||
? {
|
||||
label: 'Payment Successful',
|
||||
color: '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',
|
||||
icon: '!',
|
||||
message: '支付成功,但余额充值暂未完成,请稍后查看订单结果或联系管理员。',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +122,12 @@ function getStatusConfig(order: PublicOrderStatusSnapshot | null, locale: Locale
|
||||
|
||||
if (order.status === 'EXPIRED') {
|
||||
return locale === 'en'
|
||||
? { label: 'Order Expired', color: 'text-gray-500', icon: '⏰', message: 'This order has expired. Please create a new order.' }
|
||||
? {
|
||||
label: 'Order Expired',
|
||||
color: 'text-gray-500',
|
||||
icon: '⏰',
|
||||
message: 'This order has expired. Please create a new order.',
|
||||
}
|
||||
: { label: '订单已超时', color: 'text-gray-500', icon: '⏰', message: '订单已超时,请重新充值。' };
|
||||
}
|
||||
|
||||
@@ -224,11 +261,7 @@ function ResultContent() {
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={goBack}
|
||||
className="mt-4 text-sm text-blue-600 underline hover:text-blue-700"
|
||||
>
|
||||
<button type="button" onClick={goBack} className="mt-4 text-sm text-blue-600 underline hover:text-blue-700">
|
||||
{text.back}
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -19,12 +19,20 @@ function StripePopupContent() {
|
||||
const text = {
|
||||
init: pickLocaleText(locale, '正在初始化...', 'Initializing...'),
|
||||
orderId: pickLocaleText(locale, '订单号', 'Order ID'),
|
||||
loadFailed: pickLocaleText(locale, '支付组件加载失败,请关闭窗口重试', 'Failed to load payment component. Please close the window and try again.'),
|
||||
loadFailed: pickLocaleText(
|
||||
locale,
|
||||
'支付组件加载失败,请关闭窗口重试',
|
||||
'Failed to load payment component. Please close the window and try again.',
|
||||
),
|
||||
payFailed: pickLocaleText(locale, '支付失败,请重试', 'Payment failed. Please try again.'),
|
||||
closeWindow: pickLocaleText(locale, '关闭窗口', 'Close window'),
|
||||
redirecting: pickLocaleText(locale, '正在跳转到支付页面...', 'Redirecting to payment page...'),
|
||||
loadingForm: pickLocaleText(locale, '正在加载支付表单...', 'Loading payment form...'),
|
||||
successClosing: pickLocaleText(locale, '支付成功,窗口即将自动关闭...', 'Payment successful. This window will close automatically...'),
|
||||
successClosing: pickLocaleText(
|
||||
locale,
|
||||
'支付成功,窗口即将自动关闭...',
|
||||
'Payment successful. This window will close automatically...',
|
||||
),
|
||||
closeWindowManually: pickLocaleText(locale, '手动关闭窗口', 'Close window manually'),
|
||||
processing: pickLocaleText(locale, '处理中...', 'Processing...'),
|
||||
payAmount: pickLocaleText(locale, `支付 ¥${amount.toFixed(2)}`, `Pay ¥${amount.toFixed(2)}`),
|
||||
@@ -191,11 +199,17 @@ function StripePopupContent() {
|
||||
{'¥'}
|
||||
{amount.toFixed(2)}
|
||||
</div>
|
||||
<p className={`mt-1 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{text.orderId}: {orderId}</p>
|
||||
<p className={`mt-1 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||||
{text.orderId}: {orderId}
|
||||
</p>
|
||||
</div>
|
||||
{stripeError ? (
|
||||
<div className="space-y-3">
|
||||
<div className={`rounded-lg border p-3 text-sm ${isDark ? 'border-red-700 bg-red-900/30 text-red-400' : 'border-red-200 bg-red-50 text-red-600'}`}>{stripeError}</div>
|
||||
<div
|
||||
className={`rounded-lg border p-3 text-sm ${isDark ? 'border-red-700 bg-red-900/30 text-red-400' : 'border-red-200 bg-red-50 text-red-600'}`}
|
||||
>
|
||||
{stripeError}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => window.close()}
|
||||
@@ -207,9 +221,7 @@ function StripePopupContent() {
|
||||
) : (
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<div className="h-8 w-8 animate-spin rounded-full border-2 border-[#635bff] border-t-transparent" />
|
||||
<span className={`ml-3 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||||
{text.redirecting}
|
||||
</span>
|
||||
<span className={`ml-3 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{text.redirecting}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -227,7 +239,9 @@ function StripePopupContent() {
|
||||
{'¥'}
|
||||
{amount.toFixed(2)}
|
||||
</div>
|
||||
<p className={`mt-1 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{text.orderId}: {orderId}</p>
|
||||
<p className={`mt-1 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||||
{text.orderId}: {orderId}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{!stripeLoaded ? (
|
||||
@@ -238,9 +252,7 @@ function StripePopupContent() {
|
||||
) : stripeSuccess ? (
|
||||
<div className="py-6 text-center">
|
||||
<div className="text-5xl text-green-600">{'✓'}</div>
|
||||
<p className={`mt-3 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||||
{text.successClosing}
|
||||
</p>
|
||||
<p className={`mt-3 text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{text.successClosing}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => window.close()}
|
||||
@@ -252,7 +264,11 @@ function StripePopupContent() {
|
||||
) : (
|
||||
<>
|
||||
{stripeError && (
|
||||
<div className={`rounded-lg border p-3 text-sm ${isDark ? 'border-red-700 bg-red-900/30 text-red-400' : 'border-red-200 bg-red-50 text-red-600'}`}>{stripeError}</div>
|
||||
<div
|
||||
className={`rounded-lg border p-3 text-sm ${isDark ? 'border-red-700 bg-red-900/30 text-red-400' : 'border-red-200 bg-red-50 text-red-600'}`}
|
||||
>
|
||||
{stripeError}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
ref={stripeContainerRef}
|
||||
@@ -264,9 +280,7 @@ 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 ? 'bg-gray-400 cursor-not-allowed' : getPaymentMeta('stripe').buttonClass,
|
||||
].join(' ')}
|
||||
>
|
||||
{stripeSubmitting ? (
|
||||
|
||||
Reference in New Issue
Block a user