fix: QR 预览优化 — 移除虚线边框/圆角/padding,专业白底+微阴影
- 去掉 border-dashed / rounded-2xl / p-4(干扰扫描) - 纯白容器 + shadow-sm,干净专业 - svgToDataUrl 改用 TextEncoder(替代废弃的 unescape) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useQrState } from '../store/qrContext';
|
||||
|
||||
/** 将 SVG 字符串转为安全的 data URL(<img> 标签中浏览器会阻止 SVG 内的脚本执行) */
|
||||
/** SVG 字符串 → data URL(安全渲染,img 上下文阻止脚本执行) */
|
||||
function svgToDataUrl(svg: string): string {
|
||||
const encoded = btoa(unescape(encodeURIComponent(svg)));
|
||||
return `data:image/svg+xml;base64,${encoded}`;
|
||||
// TextEncoder 比 btoa(unescape(...)) 更可靠,正确支持 UTF-8
|
||||
const bytes = new TextEncoder().encode(svg);
|
||||
const binStr = Array.from(bytes, (b) => String.fromCharCode(b)).join('');
|
||||
return `data:image/svg+xml;base64,${btoa(binStr)}`;
|
||||
}
|
||||
|
||||
export default function QrPreview() {
|
||||
@@ -15,10 +17,13 @@ export default function QrPreview() {
|
||||
[state.preview?.svg],
|
||||
);
|
||||
|
||||
const containerCls =
|
||||
'w-64 h-64 flex items-center justify-center bg-white rounded-xl shadow-sm';
|
||||
|
||||
if (!svgDataUrl) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center gap-3 text-gray-400">
|
||||
<div className="w-64 h-64 border-2 border-dashed border-gray-300 dark:border-gray-700 rounded-2xl flex items-center justify-center bg-white/50 dark:bg-gray-800/50">
|
||||
<div className={`${containerCls} border border-gray-200`}>
|
||||
{state.loading ? (
|
||||
<span className="text-sm animate-pulse">生成中...</span>
|
||||
) : (
|
||||
@@ -31,16 +36,18 @@ export default function QrPreview() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-3">
|
||||
{/* SVG 转为 data URL 通过 <img> 渲染,浏览器在 img 上下文中阻止脚本执行 */}
|
||||
<img
|
||||
src={svgDataUrl}
|
||||
alt="QR 码"
|
||||
className="w-64 h-64 border-2 border-dashed border-gray-300 dark:border-gray-700 rounded-2xl p-4 bg-white dark:bg-white qr-preview"
|
||||
/>
|
||||
<div className="flex gap-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
<span>版本: {state.preview!.version}</span>
|
||||
{/* 纯白背景 + 微阴影,无边框/圆角干扰扫描 */}
|
||||
<div className={containerCls}>
|
||||
<img
|
||||
src={svgDataUrl}
|
||||
alt="QR 码"
|
||||
className="w-60 h-60"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-3 text-xs text-gray-400">
|
||||
<span>版本 {state.preview!.version}</span>
|
||||
<span>{state.preview!.size}×{state.preview!.size}</span>
|
||||
<span>掩码: {state.preview!.mask}</span>
|
||||
<span>掩码 {state.preview!.mask}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user