157 lines
6.8 KiB
HTML
157 lines
6.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="renderer" content="webkit">
|
||
<script>(function(){var t;try{t=localStorage.getItem("hp-theme")}catch(e){}if(!t){t=(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)?"dark":"light"}document.documentElement.setAttribute("data-theme",t);})();</script>
|
||
<title>二维码生成器</title>
|
||
<link rel="icon" href="../assets/img/logo.svg">
|
||
<link rel="stylesheet" href="../assets/css/common.css">
|
||
</head>
|
||
<body>
|
||
<div class="func-bar"><div class="wrap func-bar-inner">
|
||
<a class="btn btn-sm js-fb-back" href="index.php" title="返回功能区首页">← 返回功能区首页</a>
|
||
<span class="func-bar-title">二维码生成器</span>
|
||
<a class="btn btn-sm" href="../index.php">首页</a>
|
||
</div></div>
|
||
|
||
<main class="page-main">
|
||
<div class="wrap page-body">
|
||
<div class="panel-card">
|
||
<p class="tip" style="margin-top:0">🔒 二维码内容仅在本机浏览器内编码,不会上传服务器。组件优先加载本地 <code>assets/js/qrcode.min.js</code>,未找到时自动回退公共 CDN(仅加载代码,不含你的内容)。</p>
|
||
<div class="field-row">
|
||
<input type="text" id="qrText" placeholder="输入需要生成二维码的内容,如网址 / 文本…" style="flex:1;min-width:260px">
|
||
<button type="button" class="btn btn-primary" id="qrGen">生成二维码</button>
|
||
<button type="button" class="btn" id="qrClear">清空</button>
|
||
</div>
|
||
<div class="field-row">
|
||
<label class="fl" style="margin:0">尺寸:<b id="qrSizeVal">300</b> px</label>
|
||
<input type="range" id="qrSize" min="180" max="520" step="10" value="300" style="max-width:300px">
|
||
</div>
|
||
<div id="qrMsg"></div>
|
||
|
||
<div class="qr-stage" id="qrStage" hidden>
|
||
<div id="qrBox"></div>
|
||
<div class="field-row" style="justify-content:center">
|
||
<button type="button" class="btn" id="qrZoom">点击放大预览</button>
|
||
<button type="button" class="btn btn-primary" id="qrDl">下载 PNG</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<button type="button" class="theme-fab js-theme-btn" title="切换昼夜模式" aria-label="切换昼夜模式"><span class="js-theme-icon"></span></button>
|
||
<button type="button" class="theme-fab to-top js-to-top" title="返回顶部" aria-label="返回顶部">↑</button>
|
||
<script src="../assets/js/common.js"></script>
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
var CDNS = [
|
||
'../assets/js/qrcode.min.js', // 本地内置(离线可用)
|
||
'https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js', // 回退 1
|
||
'https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js' // 回退 2
|
||
];
|
||
function $(id) { return document.getElementById(id); }
|
||
|
||
function loadQR(cb) {
|
||
if (window.QRCode) { cb(null); return; }
|
||
var idx = 0;
|
||
(function next() {
|
||
if (window.QRCode) { cb(null); return; }
|
||
if (idx >= CDNS.length) { cb(new Error('二维码组件加载失败,请检查网络后重试,或将 qrcode.min.js 放入 assets/js/ 目录离线使用')); return; }
|
||
var s = document.createElement('script');
|
||
s.src = CDNS[idx++];
|
||
s.onload = function () { cb(window.QRCode ? null : new Error('二维码组件加载失败')); };
|
||
s.onerror = function () { next(); };
|
||
document.head.appendChild(s);
|
||
})();
|
||
}
|
||
|
||
var lastValue = '';
|
||
function generate() {
|
||
var value = $('qrText').value.trim();
|
||
var msg = $('qrMsg');
|
||
msg.innerHTML = '';
|
||
if (!value) { msg.innerHTML = '<div class="err-msg">请输入内容。</div>'; $('qrText').focus(); return; }
|
||
loadQR(function (err) {
|
||
if (err) { msg.innerHTML = '<div class="err-msg">' + err.message + '</div>'; return; }
|
||
if ($('qrText').value.trim() !== value) return;
|
||
var size = parseInt($('qrSize').value, 10);
|
||
var box = $('qrBox');
|
||
box.innerHTML = '';
|
||
try {
|
||
new QRCode(box, {
|
||
text: value,
|
||
width: size,
|
||
height: size,
|
||
colorDark: '#000000',
|
||
colorLight: '#ffffff',
|
||
correctLevel: QRCode.CorrectLevel.M
|
||
});
|
||
lastValue = value;
|
||
$('qrStage').hidden = false;
|
||
msg.innerHTML = '<div class="ok-msg">二维码已生成。</div>';
|
||
} catch (e) {
|
||
box.innerHTML = '';
|
||
msg.innerHTML = '<div class="err-msg">内容过长或生成失败,请缩短后重试。</div>';
|
||
}
|
||
});
|
||
}
|
||
|
||
function getDataURL() {
|
||
var box = $('qrBox');
|
||
var canvas = box.querySelector('canvas');
|
||
if (canvas && canvas.toDataURL) return canvas.toDataURL('image/png');
|
||
var img = box.querySelector('img');
|
||
if (img && /^data:/i.test(img.src)) return img.src;
|
||
return null;
|
||
}
|
||
|
||
function clearQR() {
|
||
$('qrText').value = '';
|
||
$('qrBox').innerHTML = '';
|
||
$('qrStage').hidden = true;
|
||
$('qrMsg').innerHTML = '';
|
||
lastValue = '';
|
||
}
|
||
|
||
$('qrGen').addEventListener('click', generate);
|
||
$('qrText').addEventListener('keydown', function (ev) { if (ev.key === 'Enter') generate(); });
|
||
$('qrSize').addEventListener('input', function () {
|
||
$('qrSizeVal').textContent = this.value;
|
||
if (lastValue) generate();
|
||
});
|
||
$('qrClear').addEventListener('click', clearQR);
|
||
|
||
$('qrDl').addEventListener('click', function () {
|
||
if (!lastValue) return;
|
||
var url = getDataURL();
|
||
if (!url) { $('qrMsg').innerHTML = '<div class="err-msg">暂无法导出图片。</div>'; return; }
|
||
var a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = 'qrcode_' + Date.now() + '.png';
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
});
|
||
|
||
$('qrZoom').addEventListener('click', function () {
|
||
if (!lastValue) return;
|
||
var url = getDataURL();
|
||
var w = window.open('', '_blank');
|
||
if (!w) { $('qrMsg').innerHTML = '<div class="err-msg">请允许浏览器弹窗以预览大图。</div>'; return; }
|
||
w.document.write('<title>二维码预览</title><body style="margin:0;background:#fff;display:flex;align-items:center;justify-content:center;min-height:100vh">');
|
||
if (url) {
|
||
w.document.write('<img src="' + url + '" style="max-width:95vw;max-height:95vh;image-rendering:pixelated">');
|
||
} else {
|
||
w.document.write('<p>无法放大预览</p>');
|
||
}
|
||
w.document.write('</body>');
|
||
});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|