Jelajahi Sumber

fix: 用 my.generateImageFromCode 替换 qrcode 库,修复收款码白屏

alphaH 2 minggu lalu
induk
melakukan
01f6012aa4
1 mengubah file dengan 45 tambahan dan 14 penghapusan
  1. 45 14
      src/pages/receive/index.tsx

+ 45 - 14
src/pages/receive/index.tsx

@@ -6,6 +6,9 @@ import { useUserStore } from '@/stores/user';
 import { requestApi } from '@/services/apis';
 import './index.less';
 
+// 支付宝小程序全局对象
+declare const my: any;
+
 const precreateTradeApi = (data: { enterpriseId: string; totalAmount: string; subject?: string }) =>
   requestApi(
     {
@@ -35,12 +38,32 @@ const STATUS_LABEL: Record<string, string> = {
   TRADE_FINISHED: '交易完成',
 };
 
+/** 调用支付宝原生 API my.generateImageFromCode 生成二维码 base64 */
+const generateQRBase64 = (code: string, size: number): Promise<string> => {
+  return new Promise((resolve, reject) => {
+    if (typeof my === 'undefined' || typeof my.generateImageFromCode !== 'function') {
+      reject(new Error('my.generateImageFromCode 不可用(基础库需 ≥1.14.0)'));
+      return;
+    }
+    my.generateImageFromCode({
+      code,
+      format: 'QRCODE',
+      width: size,
+      height: size,
+      correctLevel: 'H',
+      success: (res: { image: string }) => resolve(res.image),
+      fail: (err: any) => reject(err),
+    });
+  });
+};
+
 export default function Receive() {
   const [statusBarHeight, setStatusBarHeight] = useState(0);
   const [amount, setAmount] = useState('');
   const [loading, setLoading] = useState(false);
   const [qrCode, setQrCode] = useState('');
   const [qrImage, setQrImage] = useState('');
+  const [qrError, setQrError] = useState('');
   const [outTradeNo, setOutTradeNo] = useState('');
   const [tradeStatus, setTradeStatus] = useState('');
   const [tradeAmount, setTradeAmount] = useState('');
@@ -59,6 +82,22 @@ export default function Receive() {
     };
   }, []);
 
+  // qrCode 变化时自动调用官方 API 生成二维码
+  useEffect(() => {
+    if (!qrCode) return;
+    setQrError('');
+    setQrImage('');
+
+    generateQRBase64(qrCode, 260)
+      .then((image) => {
+        setQrImage(image.startsWith('data:') ? image : 'data:image/png;base64,' + image);
+      })
+      .catch((e) => {
+        console.error('[QR] 生成失败', e);
+        setQrError((e && e.message) || '二维码生成失败');
+      });
+  }, [qrCode]);
+
   const showToast = (options: ToastOptions) => {
     Toast.show('receive-toast', options);
   };
@@ -79,16 +118,6 @@ export default function Receive() {
     setAmount(filtered);
   };
 
-  const generateQrImage = async (url: string) => {
-    try {
-      const QRCode = require('qrcode');
-      const dataUrl = await QRCode.toDataURL(url, { width: 260, margin: 1 });
-      setQrImage(dataUrl);
-    } catch (_) {
-      setQrImage(url);
-    }
-  };
-
   const startPolling = (tradeNo: string) => {
     if (pollingRef.current) clearInterval(pollingRef.current);
     pollingRef.current = setInterval(async () => {
@@ -129,8 +158,6 @@ export default function Receive() {
       setQrCode(result.qrCode);
       setOutTradeNo(result.outTradeNo);
       setTradeStatus('');
-      setQrImage('');
-      await generateQrImage(result.qrCode);
       startPolling(result.outTradeNo);
     } catch (e: any) {
       showToast({ icon: 'error', content: e.message || '生成收款码失败' });
@@ -182,10 +209,12 @@ export default function Receive() {
             <Text className="qr-title">客户扫码付款</Text>
 
             <View className="qr-code">
-              {qrImage && qrImage.startsWith('data:') ? (
+              {qrImage ? (
                 <Image src={qrImage} mode="aspectFit" style={{ width: 260, height: 260 }} />
+              ) : qrError ? (
+                <Text style={{ color: '#ff4d4f', fontSize: 14 }}>{qrError}</Text>
               ) : (
-                <Image src={qrCode} mode="aspectFit" style={{ width: 260, height: 260 }} />
+                <Text style={{ color: '#999', fontSize: 14 }}>二维码生成中…</Text>
               )}
             </View>
 
@@ -213,6 +242,8 @@ export default function Receive() {
                 block
                 onClick={() => {
                   setQrCode('');
+                  setQrImage('');
+                  setQrError('');
                   setAmount('');
                   setTradeStatus('');
                 }}