ALIEZ 1 tháng trước cách đây
mục cha
commit
f5a89e517c

+ 1 - 0
src/app/[locale]/account/orders/page.tsx

@@ -79,6 +79,7 @@ export default function AccountOrdersPage() {
       setOrders(res.list);
       setTotal(res.page.total);
       setCancelTarget(null);
+      window.location.reload();
     } catch (e) {
       const err = e as Error;
       setError(err.message || "取消订单失败,请稍后重试。");

+ 1 - 0
src/app/[locale]/account/page.tsx

@@ -151,6 +151,7 @@ export default function AccountPage() {
       await cancelOrder(cancelTarget.id);
       await reloadOrders();
       setCancelTarget(null);
+      window.location.reload();
     } catch (error) {
       const e = error as Error;
       setOrdersError(e.message || "取消订单失败,请稍后重试。");

+ 15 - 11
src/app/[locale]/checkout/checkout-form.tsx

@@ -9,6 +9,7 @@ import { useAuth } from "@/providers/auth-provider";
 import {
   fetchBankChannelOptions,
   fetchRemittanceChannels,
+  isTelegraphicStylePayRequestUrl,
   submitXfgPayOrder,
   type BankChannelOption,
   type RemittanceChannel,
@@ -43,7 +44,7 @@ export function CheckoutForm() {
   const [bankOptionsError, setBankOptionsError] = useState<string | null>(null);
   const [selectedBankCode, setSelectedBankCode] = useState("");
   const [depositAmount, setDepositAmount] = useState("");
-  const [msg, setMsg] = useState<string | null>(null);
+  const [, setMsg] = useState<string | null>(null);
   const [submitting, setSubmitting] = useState(false);
   const [submitDialog, setSubmitDialog] = useState<{
     open: boolean;
@@ -120,15 +121,18 @@ export function CheckoutForm() {
         status: "loading",
         message: "订单提交中,请稍候...",
       });
+      const requestUrl = selectedChannel?.requestUrl || "/xfgpay/pay";
+      const isTelegraphicPay = isTelegraphicStylePayRequestUrl(requestUrl);
       const { resultUrl } = await submitXfgPayOrder({
-        requestUrl: selectedChannel?.requestUrl || "/xfgpay/pay",
+        requestUrl,
         amount: finalAmount,
         bankCode: selectedBankCode || undefined,
+        code: selectedChannel?.code || undefined,
         goodIds: [goodsId],
         payName: "",
         payPhone: "",
       });
-      if (!resultUrl) {
+      if (!resultUrl && !isTelegraphicPay) {
         throw new Error("下单成功但未返回支付地址");
       }
       addMockOrder({
@@ -139,11 +143,13 @@ export function CheckoutForm() {
       setSubmitDialog({
         open: true,
         status: "success",
-        message: "提交订单成功,正在跳转到支付页面...",
+        message: isTelegraphicPay ? "提交订单成功。" : "提交订单成功,正在跳转到支付页面...",
       });
-      setTimeout(() => {
-        window.open(resultUrl, "_blank", "noopener,noreferrer");
-      }, 1000);
+      if (resultUrl) {
+        setTimeout(() => {
+          window.open(resultUrl, "_blank", "noopener,noreferrer");
+        }, 1000);
+      }
     } catch (error) {
       const e = error as Error;
       setSubmitDialog({
@@ -323,8 +329,6 @@ export function CheckoutForm() {
         </p>
       )}
 
-      {msg && <p className="text-sm text-emerald-700">{msg}</p>}
-
       {submitDialog.open ? (
         <ModalShell open={submitDialog.open} className="max-w-sm">
           <div className="w-full rounded-2xl border border-[var(--border)] bg-[var(--card)] p-6 shadow-xl">
@@ -351,13 +355,13 @@ export function CheckoutForm() {
                 <p className="mt-1 text-sm text-[var(--muted)]">{submitDialog.message}</p>
               </div>
             </div>
-            {submitDialog.status === "error" ? (
+            {submitDialog.status !== "loading" ? (
               <button
                 type="button"
                 onClick={() => setSubmitDialog((prev) => ({ ...prev, open: false }))}
                 className="mt-5 w-full rounded-lg border border-[var(--border)] px-3 py-2 text-sm hover:bg-[var(--background)]"
               >
-                知道了
+                {submitDialog.status === "success" ? "确定" : "知道了"}
               </button>
             ) : null}
           </div>

+ 11 - 0
src/lib/api.ts

@@ -69,6 +69,16 @@ export class ApiError extends Error {
   }
 }
 
+let authTimeoutDialogShown = false;
+
+function notifySessionTimeoutAndRedirect() {
+  if (typeof window === "undefined") return;
+  if (authTimeoutDialogShown) return;
+  authTimeoutDialogShown = true;
+  window.alert("登录超时,请重新登录");
+  window.location.assign("/auth/login");
+}
+
 function isPlainObject(v: unknown): v is Record<string, unknown> {
   return typeof v === "object" && v !== null && !Array.isArray(v);
 }
@@ -92,6 +102,7 @@ api.interceptors.response.use(
     if (!isPlainObject(body) || !("code" in body)) return res;
     if (body.code === 600 || body.code === "600") {
       setApiAuthToken(null);
+      notifySessionTimeoutAndRedirect();
       return Promise.reject(new ApiError("登录状态失效,请重新登录", 600, body));
     }
     if (isBusinessSuccessCode(body.code)) return res;

+ 2 - 0
src/lib/checkout-api.ts

@@ -207,6 +207,7 @@ export async function submitXfgPayOrder(input: {
   requestUrl: string;
   amount: number;
   bankCode?: string;
+  code?: string;
   goodIds: string[];
   payName: string;
   payPhone: string;
@@ -229,6 +230,7 @@ export async function submitXfgPayOrder(input: {
         payName: input.payName,
         payPhone: input.payPhone,
         amount: input.amount,
+        ...(input.code ? { code: input.code } : {}),
         ...(input.bankCode ? { bankCode: input.bankCode } : {}),
       }
     : {