From 50cd4c57609007a28de160ee668374d9ceb8b7ca Mon Sep 17 00:00:00 2001 From: Eamon-meng <17516219072@163.com> Date: Sun, 22 Jun 2025 14:42:21 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B4=AD=E4=B9=B0=E5=A5=97=E9=A4=90=E9=87=8C?= =?UTF-8?q?=E5=8E=BB=E5=85=85=E5=80=BC=E6=A1=8C=E9=9D=A2=E7=AB=AF=E5=92=8C?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E7=AB=AF=E6=94=AF=E4=BB=98=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/admin/bills/page.tsx | 2 +- .../admin/bills}/payment-dialog.tsx | 0 .../payment => app/admin/bills}/payment.tsx | 0 .../composites/payment/desktop-payment.tsx | 114 ++++++ src/components/composites/payment/index.ts | 30 +- .../composites/payment/mobile-payment.tsx | 117 +++++++ .../composites/payment/payment-button.tsx | 56 +++ .../composites/payment/payment-modal.tsx | 43 +++ .../composites/payment/payment-status.tsx | 26 ++ src/components/composites/payment/types.tsx | 31 ++ src/components/composites/purchase/pay.tsx | 298 ++++++---------- src/components/composites/recharge/index.tsx | 327 +++++++----------- src/lib/models/trade.ts | 133 +++---- 13 files changed, 713 insertions(+), 464 deletions(-) rename src/{components/composites/payment => app/admin/bills}/payment-dialog.tsx (100%) rename src/{components/composites/payment => app/admin/bills}/payment.tsx (100%) create mode 100644 src/components/composites/payment/desktop-payment.tsx create mode 100644 src/components/composites/payment/mobile-payment.tsx create mode 100644 src/components/composites/payment/payment-button.tsx create mode 100644 src/components/composites/payment/payment-modal.tsx create mode 100644 src/components/composites/payment/payment-status.tsx create mode 100644 src/components/composites/payment/types.tsx diff --git a/src/app/admin/bills/page.tsx b/src/app/admin/bills/page.tsx index fd49bfe..da87056 100644 --- a/src/app/admin/bills/page.tsx +++ b/src/app/admin/bills/page.tsx @@ -16,7 +16,7 @@ import zod from 'zod' import {zodResolver} from '@hookform/resolvers/zod' import {Label} from '@/components/ui/label' import Page from '@/components/page' -import {PaymentStatusCell} from '@/components/composites/payment' +import {PaymentStatusCell} from './payment' const filterSchema = zod.object({ type: zod.enum(['all', '3', '1', '2']).default('all'), diff --git a/src/components/composites/payment/payment-dialog.tsx b/src/app/admin/bills/payment-dialog.tsx similarity index 100% rename from src/components/composites/payment/payment-dialog.tsx rename to src/app/admin/bills/payment-dialog.tsx diff --git a/src/components/composites/payment/payment.tsx b/src/app/admin/bills/payment.tsx similarity index 100% rename from src/components/composites/payment/payment.tsx rename to src/app/admin/bills/payment.tsx diff --git a/src/components/composites/payment/desktop-payment.tsx b/src/components/composites/payment/desktop-payment.tsx new file mode 100644 index 0000000..010e817 --- /dev/null +++ b/src/components/composites/payment/desktop-payment.tsx @@ -0,0 +1,114 @@ +'use client' +import {DialogContent, DialogHeader, DialogTitle} from '@/components/ui/dialog' +import {Button} from '@/components/ui/button' +import {completeResource} from '@/actions/resource' +import {toast} from 'sonner' +import {CheckCircle, Loader} from 'lucide-react' +import {useState, useEffect, useRef} from 'react' +import * as qrcode from 'qrcode' +import Image from 'next/image' +import wechat from '@/components/composites/purchase/_assets/wechat.svg' +import alipay from '@/components/composites/purchase/_assets/alipay.svg' +import {PaymentMethod} from './types' + +interface Trade { + inner_no: string + method: number + pay_url: string + amount?: number + status?: number +} +export function DesktopPayment({trade, onClose}: {trade: Trade, onClose: () => void}) { + const [paymentVerified, setPaymentVerified] = useState(false) + const [loading, setLoading] = useState(false) + const canvasRef = useRef(null) + + const paymentInfo = { + icon: trade.method === PaymentMethod.Alipay ? alipay : wechat, + name: trade.method === PaymentMethod.Alipay ? '支付宝' : '微信支付', + } + + useEffect(() => { + if (!canvasRef.current || trade.method === 1) return + qrcode.toCanvas(canvasRef.current, trade.pay_url, {width: 200}) + .catch((err) => { + console.error('生成二维码失败:', err) + toast.error('生成支付二维码失败') + }) + }, [trade.method, trade.pay_url]) + + const handleComplete = async () => { + setLoading(true) + try { + const resp = await completeResource({trade_no: trade.inner_no}) + if (!resp.success) throw new Error(resp.message) + toast.success('支付成功') + setPaymentVerified(true) + setTimeout(onClose, 2000) + } + catch (e) { + toast.error('支付验证失败', {description: (e as Error).message}) + } + finally { + setLoading(false) + } + } + + return ( + + + + {paymentInfo.name} + {paymentInfo.name} + + + + {paymentVerified ? ( +
+ +

支付验证成功

+
+ ) : ( +
+
+ {trade.method === 1 ? ( +