zhang
7 小时以前 70930071a49190f414c8d8bc9c9e9795a4096739
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import React, { useEffect, useState } from 'react';
import { toDataURL } from 'qrcode';
import { Box, Skeleton, Typography, useTheme } from '@mui/material';
 
const CodeQr = ({ value, size = 160, loading }) => {
    const [dataUrl, setDataUrl] = useState(null);
    const theme = useTheme();
 
    useEffect(() => {
        let ignore = false;
        if (!value) {
            setDataUrl(null);
            return () => { ignore = true; };
        }
        const darkColor = theme.palette.mode === 'dark' ? '#f5f6fa' : '#111111';
        const lightColor = theme.palette.mode === 'dark' ? '#1b1b1b' : '#fafafa';
        toDataURL(String(value), {
            width: size,
            margin: 2,
            color: {
                dark: darkColor,
                light: lightColor
            },
        }).then((url) => {
            if (!ignore) {
                setDataUrl(url);
            }
        }).catch((error) => {
            console.error('QR render failed', error);
            if (!ignore) {
                setDataUrl(null);
            }
        });
        return () => {
            ignore = true;
        };
    }, [value, size, theme.palette.mode]);
 
    if (loading) {
        return <Skeleton variant="rectangular" height={size} width={size} sx={{ borderRadius: 2 }} />;
    }
 
    if (!value || !dataUrl) {
        return (
            <Typography variant="body2" color="text.disabled">
                -
            </Typography>
        );
    }
 
    return (
        <Box
            component="img"
            src={dataUrl}
            alt="Code QR"
            sx={{
                width: size,
                height: size,
                borderRadius: 2,
                boxShadow: (theme) => theme.shadows[3],
                p: 1,
                backgroundColor: 'background.paper'
            }}
        />
    );
};
 
export default CodeQr;