这是一个基于 HTML、Tailwind CSS 和 JavaScript 构建的纯前端二维码生成与解析工具,无需后端部署,打开即用。它主要具备以下特点:
-
核心功能:支持将文本或网址快速生成二维码,并可下载为高清图片;同时支持上传二维码图片,智能解析其中的内容。
-
技术亮点:采用 Tailwind CSS 实现响应式布局与玻璃拟态 UI,结合 AOS 和 GSAP 增强页面交互动效,通过调用免费 API 完成二维码的编解码。
-
适配体验:完美兼容移动端和桌面端,加载状态、错误提示等细节处理到位,交互体验流畅自然。
如果你想要其他风格(如更简洁、更营销化),也可以告诉我,我会帮你进一步调整。
直接展出代码:
(可以复制代码在:代码在线运行工具 - 墨桅博客 看效果)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>二维码生成与解析工具 - 墨桅博客</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#64748b',
success: '#10b981',
warning: '#f59e0b',
danger: '#ef4444',
dark: '#1e293b',
light: '#f8fafc'
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif']
},
boxShadow: {
'card': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
'hover': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)'
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.glass-effect {
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
}
.btn-primary {
background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
transition: all 0.3s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(59, 130, 246, 0.3);
}
.btn-secondary {
background: linear-gradient(135deg, #64748b 0%, #475569 100%);
transition: all 0.3s ease;
}
.btn-secondary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(100, 116, 139, 0.3);
}
}
</style>
<script>
// 墨桅博客 https://www.jetmast.com
</script>
</head>
<body class="bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 min-h-screen">
<div class="container mx-auto px-4 py-12">
<header class="text-center mb-12">
<div class="inline-block p-2 bg-white rounded-full shadow-lg mb-4" data-aos="fade-down">
<i class="fa fa-qrcode text-5xl text-primary"></i>
</div>
<h1 class="text-5xl font-bold text-dark mb-3" data-aos="fade-up" data-aos-delay="100">二维码生成与解析工具</h1>
<p class="text-xl text-gray-600 max-w-2xl mx-auto" data-aos="fade-up" data-aos-delay="200">
快速生成和解析二维码,支持自定义内容,提供高质量图片下载
</p>
</header>
<main class="max-w-7xl mx-auto">
<div class="flex flex-col lg:flex-row gap-8">
<div class="glass-effect rounded-2xl shadow-card p-8 card-hover flex-1" data-aos="fade-right" data-aos-delay="100">
<div class="flex items-center mb-6">
<div class="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center mr-4">
<i class="fa fa-qrcode text-2xl text-primary"></i>
</div>
<h2 class="text-2xl font-bold text-dark">生成二维码</h2>
</div>
<div class="space-y-6">
<div>
<label class="block text-lg font-medium text-gray-700 mb-3">输入内容</label>
<textarea id="qr-content" rows="4" class="w-full px-4 py-3 text-lg border border-gray-300 rounded-xl focus:outline-none focus:ring-3 focus:ring-primary/50 transition-all" placeholder="请输入要生成二维码的文本或网址..."></textarea>
</div>
<button onclick="generateQRCode()" class="w-full btn-primary text-white font-semibold py-4 px-6 rounded-xl text-lg shadow-lg">
<i class="fa fa-qrcode mr-3"></i>生成二维码
</button>
<div id="result-container" class="hidden">
<div class="bg-white rounded-xl p-6 text-center shadow-lg border border-gray-100">
<div class="inline-block p-4 bg-gray-50 rounded-lg mb-6">
<img id="qr-image" src="" alt="二维码" class="mx-auto w-40 h-40 object-contain">
</div>
<div class="flex justify-center space-x-4">
<button onclick="downloadQRCode()" class="bg-success hover:bg-green-600 text-white px-6 py-3 rounded-lg text-base font-medium transition-all hover:shadow-lg">
<i class="fa fa-download mr-2"></i>下载二维码
</button>
</div>
</div>
</div>
<div id="loading-container" class="hidden">
<div class="text-center py-12">
<div class="inline-block">
<i class="fa fa-spinner fa-spin text-4xl text-primary mb-4"></i>
</div>
<p class="text-lg text-gray-600 font-medium">正在生成二维码...</p>
</div>
</div>
<div id="error-container" class="hidden">
<div class="bg-red-50 border border-red-200 rounded-xl p-6 shadow-md">
<div class="flex items-start">
<div class="bg-red-100 rounded-full p-3 mr-4">
<i class="fa fa-exclamation-circle text-red-500 text-xl"></i>
</div>
<div>
<h3 class="text-lg font-semibold text-red-800 mb-2">生成失败</h3>
<p id="error-message" class="text-base text-red-700"></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="glass-effect rounded-2xl shadow-card p-8 card-hover flex-1" data-aos="fade-left" data-aos-delay="200">
<div class="flex items-center mb-6">
<div class="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center mr-4">
<i class="fa fa-search text-2xl text-secondary"></i>
</div>
<h2 class="text-2xl font-bold text-dark">解析二维码</h2>
</div>
<div class="space-y-6">
<div>
<label class="block text-lg font-medium text-gray-700 mb-3">上传二维码图片</label>
<div class="relative">
<input type="file" id="qr-file" accept="image/*" class="absolute inset-0 w-full h-full opacity-0 cursor-pointer">
<div class="border-2 border-dashed border-gray-300 rounded-xl p-8 text-center transition-all hover:border-secondary">
<i class="fa fa-cloud-upload text-4xl text-gray-400 mb-4"></i>
<p class="text-gray-600 mb-2">点击或拖拽文件到此处上传</p>
<p class="text-sm text-gray-500">支持 JPG、PNG、WEBP 格式</p>
</div>
</div>
</div>
<button onclick="decodeQRCode()" class="w-full btn-secondary text-white font-semibold py-4 px-6 rounded-xl text-lg shadow-lg">
<i class="fa fa-search mr-3"></i>解析二维码
</button>
<div id="decode-result" class="hidden">
<div class="bg-white rounded-xl p-6 shadow-lg border border-gray-100">
<div class="flex items-center mb-4">
<div class="w-8 h-8 bg-green-100 rounded-lg flex items-center justify-center mr-3">
<i class="fa fa-check text-success"></i>
</div>
<h3 class="text-xl font-semibold text-gray-800">解析结果</h3>
</div>
<div id="decode-content" class="text-base font-mono bg-gray-50 p-4 border border-gray-200 rounded-lg break-all max-h-40 overflow-y-auto"></div>
</div>
</div>
</div>
</div>
</div>
</main>
<footer class="text-center text-gray-600 mt-16">
<div class="glass-effect inline-block px-8 py-4 rounded-full shadow-md">
<p id="copyright" class="text-lg font-medium"></p>
</div>
</footer>
</div>
<script>
function initCopyright() {
const owner = '墨桅博客';
const year = new Date().getFullYear();
document.getElementById('copyright').textContent = `© ${year} ${owner} 保留所有权利`;
}
function generateQRCode() {
const content = document.getElementById('qr-content').value.trim();
if (!content) {
showError('请输入要生成二维码的内容');
return;
}
document.getElementById('result-container').style.display = 'none';
document.getElementById('error-container').style.display = 'none';
document.getElementById('loading-container').style.display = 'block';
const apiUrl = `https://v2.xxapi.cn/api/qrcode?text=${encodeURIComponent(content)}&return=json`;
console.log('调用API:', apiUrl);
fetch(apiUrl)
.then(response => {
if (!response.ok) {
throw new Error('API请求失败: ' + response.status);
}
return response.json();
})
.then(data => {
console.log('API响应:', data);
document.getElementById('loading-container').style.display = 'none';
if (data.code === '200' || data.code === 200) {
const qrImage = document.getElementById('qr-image');
qrImage.src = data.data;
qrImage.style.width = '200px';
qrImage.style.height = '200px';
document.getElementById('result-container').style.display = 'block';
} else {
showError(data.msg || '生成失败,请重试');
}
})
.catch(error => {
console.error('生成失败:', error);
document.getElementById('loading-container').style.display = 'none';
showError('生成失败: ' + error.message);
});
}
function downloadQRCode() {
const qrImage = document.getElementById('qr-image');
if (!qrImage.src) return;
const link = document.createElement('a');
link.href = qrImage.src;
link.download = '二维码.png';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// 使用 jsQR 库在客户端本地解析二维码,不再依赖外部API
function decodeQRCode() {
const fileInput = document.getElementById('qr-file');
const file = fileInput.files[0];
if (!file) {
alert('请选择要解析的二维码图片');
return;
}
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
// 创建 canvas 绘制图片
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
// 获取图像数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 使用 jsQR 解码
const code = jsQR(imageData.data, canvas.width, canvas.height);
if (code) {
document.getElementById('decode-content').textContent = code.data;
document.getElementById('decode-result').style.display = 'block';
} else {
alert('未能识别二维码,请确保图片包含清晰的二维码');
}
};
img.onerror = function() {
alert('图片加载失败,请检查文件格式');
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}
function showError(message) {
document.getElementById('loading-container').style.display = 'none';
document.getElementById('error-message').textContent = message;
document.getElementById('error-container').style.display = 'block';
}
document.addEventListener('DOMContentLoaded', function() {
initCopyright();
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true
});
console.log('二维码工具已初始化');
const fileInput = document.getElementById('qr-file');
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const uploadArea = this.parentElement.querySelector('.border');
uploadArea.classList.add('border-success');
uploadArea.classList.remove('border-gray-300', 'hover:border-secondary');
}
});
});
</script>
</body>
</html>

请登录后发表评论
注册
停留在世界边缘,与之惜别