* refactor(engine): 重构2D渲染管线坐标系统 * feat(engine): 完善2D渲染管线和编辑器视口功能 * feat(editor): 实现Viewport变换工具系统 * feat(editor): 优化Inspector渲染性能并修复Gizmo变换工具显示 * feat(editor): 实现Run on Device移动预览功能 * feat(editor): 添加组件属性控制和依赖关系系统 * feat(editor): 实现动画预览功能和优化SpriteAnimator编辑器 * feat(editor): 修复SpriteAnimator动画预览功能并迁移CI到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(ci): 迁移项目到pnpm并修复CI构建问题 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 移除 network 相关包 * chore: 移除 network 相关包
90 lines
3.0 KiB
TypeScript
90 lines
3.0 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { X, Copy, Check } from 'lucide-react';
|
|
import { TauriAPI } from '../api/tauri';
|
|
import '../styles/QRCodeDialog.css';
|
|
|
|
interface QRCodeDialogProps {
|
|
url: string;
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export const QRCodeDialog: React.FC<QRCodeDialogProps> = ({ url, isOpen, onClose }) => {
|
|
const [qrCodeData, setQrCodeData] = useState<string>('');
|
|
const [copied, setCopied] = useState(false);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (isOpen && url) {
|
|
setLoading(true);
|
|
TauriAPI.generateQRCode(url)
|
|
.then((base64) => {
|
|
setQrCodeData(`data:image/png;base64,${base64}`);
|
|
})
|
|
.catch((error) => {
|
|
console.error('Failed to generate QR code:', error);
|
|
})
|
|
.finally(() => {
|
|
setLoading(false);
|
|
});
|
|
}
|
|
}, [isOpen, url]);
|
|
|
|
const handleCopy = async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(url);
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
} catch (error) {
|
|
console.error('Failed to copy URL:', error);
|
|
}
|
|
};
|
|
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="qrcode-dialog-overlay">
|
|
<div className="qrcode-dialog">
|
|
<div className="qrcode-dialog-header">
|
|
<h3>扫码在移动设备上预览</h3>
|
|
<button className="qrcode-dialog-close" onClick={onClose}>
|
|
<X size={18} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="qrcode-dialog-content">
|
|
{loading ? (
|
|
<div className="qrcode-loading">生成二维码中...</div>
|
|
) : qrCodeData ? (
|
|
<img src={qrCodeData} alt="QR Code" width={200} height={200} />
|
|
) : (
|
|
<div className="qrcode-error">生成失败</div>
|
|
)}
|
|
|
|
<div className="qrcode-url-container">
|
|
<input
|
|
type="text"
|
|
value={url}
|
|
readOnly
|
|
className="qrcode-url-input"
|
|
/>
|
|
<button
|
|
className="qrcode-copy-button"
|
|
onClick={handleCopy}
|
|
title={copied ? '已复制' : '复制链接'}
|
|
>
|
|
{copied ? <Check size={16} /> : <Copy size={16} />}
|
|
</button>
|
|
</div>
|
|
|
|
<p className="qrcode-hint">
|
|
确保手机和电脑在同一局域网内
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default QRCodeDialog;
|