refactor(clipboard): 重构剪贴板工具函数并优化相关组件
将 copyToClipboard 拆分为 copyTextToClipboard 和 copyImageToClipboard 移除 useClipboard hook 并将消息处理移至调用方 优化组件中的剪贴板操作错误处理逻辑
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||
import { IconButton, Tooltip } from '@mui/material';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import { copyToClipboard } from '@/utils/clipboard';
|
||||
import { copyTextToClipboard } from '@/utils/clipboard';
|
||||
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
||||
|
||||
/**
|
||||
@@ -45,11 +45,15 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
|
||||
|
||||
const handleCopy = async () => {
|
||||
if (text) {
|
||||
const success = await copyToClipboard(text, showMessage);
|
||||
if (success) {
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1500);
|
||||
}
|
||||
await copyTextToClipboard(text)
|
||||
.then(() => {
|
||||
showMessage?.('复制成功', { severity: 'success' });
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1500);
|
||||
})
|
||||
.catch(() => {
|
||||
showMessage?.('复制失败', { severity: 'error' });
|
||||
});
|
||||
} else {
|
||||
showMessage?.('无内容可复制', { severity: 'error' });
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import QRious from 'qrious';
|
||||
import { qrCodePageStyles } from '@/config/pageTheme';
|
||||
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
||||
import { copyImageToClipboard } from '@/utils/clipboard';
|
||||
|
||||
interface UrlToQrCodeSectionProps {
|
||||
expanded: boolean;
|
||||
@@ -80,27 +81,21 @@ const UrlToQrCodeSection = ({
|
||||
link.href = qrCodeDataUrl;
|
||||
link.download = 'qrcode.png';
|
||||
link.click();
|
||||
showMessage('二维码下载成功', { severity: 'success', autoHideDuration: 300 });
|
||||
showMessage('二维码下载成功', { severity: 'success' });
|
||||
};
|
||||
|
||||
const copyQrCode = async () => {
|
||||
if (!qrCodeDataUrl) return;
|
||||
|
||||
try {
|
||||
const response = await fetch(qrCodeDataUrl);
|
||||
const blob = await response.blob();
|
||||
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
'image/png': blob,
|
||||
}),
|
||||
]);
|
||||
|
||||
showMessage('二维码已复制到剪贴板', { severity: 'success', autoHideDuration: 1000 });
|
||||
} catch (error) {
|
||||
console.error('复制二维码失败:', error);
|
||||
showMessage('复制二维码失败,请重试', { severity: 'error', autoHideDuration: 300 });
|
||||
}
|
||||
const response = await fetch(qrCodeDataUrl);
|
||||
const blob = await response.blob();
|
||||
await copyImageToClipboard(blob)
|
||||
.then(() => {
|
||||
showMessage('二维码已复制到剪贴板', { severity: 'success' });
|
||||
})
|
||||
.catch(() => {
|
||||
showMessage('复制二维码失败,请重试', { severity: 'error' });
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+29
-27
@@ -1,37 +1,39 @@
|
||||
import type { SnackbarOptions } from '@/components/GlobalSnackbar';
|
||||
import { useSnackbarState } from '@/components/GlobalSnackbar';
|
||||
|
||||
/**
|
||||
* 复制文本到剪贴板
|
||||
* @param text 要复制的文本
|
||||
* @param showMessage 显示消息的函数
|
||||
* @returns Promise<boolean> 是否复制成功
|
||||
*/
|
||||
export const copyToClipboard = async (
|
||||
text: string,
|
||||
showMessage?: (message: string, options?: SnackbarOptions) => void,
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
showMessage?.('已复制', { severity: 'success' });
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('复制失败:', error);
|
||||
showMessage?.('复制失败', { severity: 'error' });
|
||||
return false;
|
||||
}
|
||||
export const copyTextToClipboard = async (text: string): Promise<boolean> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch(() => {
|
||||
reject(false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 自定义 Hook: 用于处理剪贴板操作
|
||||
* @returns 包含复制函数和 snackbarProps 的对象
|
||||
* 复制图片到剪贴板
|
||||
* @param blob 要复制的图片
|
||||
* @returns Promise<boolean> 是否复制成功
|
||||
*/
|
||||
export const useClipboard = () => {
|
||||
const { snackbarProps, showMessage } = useSnackbarState({ autoHideDuration: 1500 });
|
||||
|
||||
const copy = async (text: string): Promise<boolean> => {
|
||||
return copyToClipboard(text, showMessage);
|
||||
};
|
||||
|
||||
return { copy, snackbarProps };
|
||||
export const copyImageToClipboard = async (blob: Blob): Promise<boolean> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.clipboard
|
||||
.write([
|
||||
new ClipboardItem({
|
||||
'image/png': blob,
|
||||
}),
|
||||
])
|
||||
.then(() => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch(() => {
|
||||
reject(false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user