Files
web_hgtv_h5/app/static/js/pages/downloadAppDialog.js
T
谢宇宁andClaude Opus 5.5 3639d2184a Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 14:47:17 +07:00

303 lines
8.4 KiB
JavaScript

(function () {
var mask = document.getElementById("downloadAppDialog");
if (!mask) return;
var pcQRBox = mask.querySelector("[data-download-qr-box]");
var h5QRBox = null;
var h5URLEl = mask.querySelector("[data-download-url]");
var downloadCTA = mask.querySelector("[data-download-app-cta]");
var copyBtn = mask.querySelector("[data-download-copy]");
var platformBtns = mask.querySelectorAll("[data-download-platform]");
var copyTimer = null;
var qrReady = false;
var qrcodeLoading = null;
function loadQRCodeLib() {
if (typeof window.QRCode === "function") {
return Promise.resolve();
}
if (qrcodeLoading) return qrcodeLoading;
qrcodeLoading = new Promise(function (resolve, reject) {
var s = document.createElement("script");
s.src = "/static/common/qrcode.min.js";
s.async = true;
s.onload = function () { resolve(); };
s.onerror = function () { reject(new Error("qrcode load failed")); };
document.head.appendChild(s);
});
return qrcodeLoading;
}
function getAppConfig() {
return window.__APP_CONFIG__ || {};
}
/** 二维码、跳转和复制链接统一使用 config/info.newAddressInfo.appAddr。 */
function getAppURL() {
var cfg = getAppConfig();
var fromCfg = String((cfg && cfg.appAddr) || "").trim();
if (fromCfg) return fromCfg;
return String(mask.getAttribute("data-download-app-url") || "").trim();
}
function isHTTPURL(value) {
return /^https?:\/\//i.test(String(value || "").trim());
}
function isMobileViewport() {
return typeof window.matchMedia === "function"
? window.matchMedia("(max-width: 767px)").matches
: (window.innerWidth || 0) <= 767;
}
function qrLevels() {
var QR = window.QRCode;
if (QR && QR.CorrectLevel) {
return [QR.CorrectLevel.L, QR.CorrectLevel.M, QR.CorrectLevel.Q, QR.CorrectLevel.H];
}
return [1, 0, 3, 2];
}
function paintQRModel(model, size) {
if (!model || typeof model.getModuleCount !== "function") return null;
var n = model.getModuleCount();
if (!n) return null;
var canvas = document.createElement("canvas");
canvas.width = size;
canvas.height = size;
var ctx = canvas.getContext("2d");
if (!ctx) return null;
ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, size, size);
var cell = size / n;
ctx.fillStyle = "#000000";
for (var row = 0; row < n; row++) {
for (var col = 0; col < n; col++) {
if (model.isDark(row, col)) {
ctx.fillRect(
Math.floor(col * cell),
Math.floor(row * cell),
Math.ceil(cell),
Math.ceil(cell)
);
}
}
}
return canvas;
}
function encodeQRCanvas(text, size) {
var QR = window.QRCode;
if (typeof QR !== "function") return null;
var holder = document.createElement("div");
holder.style.cssText =
"position:fixed;left:0;top:0;width:" +
size +
"px;height:" +
size +
"px;opacity:0;pointer-events:none;z-index:-1;";
document.body.appendChild(holder);
var levels = qrLevels();
try {
for (var i = 0; i < levels.length; i++) {
holder.innerHTML = "";
try {
var inst = new QR(holder, {
text: text,
width: size,
height: size,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: levels[i],
});
var painted = paintQRModel(inst && inst._oQRCode, size);
if (painted) return painted;
var srcCanvas = holder.querySelector("canvas");
if (srcCanvas) {
var copy = document.createElement("canvas");
copy.width = size;
copy.height = size;
copy.getContext("2d").drawImage(srcCanvas, 0, 0, size, size);
return copy;
}
} catch (e) {
/* try next level */
}
}
return null;
} finally {
if (holder.parentNode) holder.parentNode.removeChild(holder);
}
}
function renderQR(el, text, size) {
if (!el || !text) return false;
el.innerHTML = "";
var img = document.createElement("img");
img.alt = "下载二维码";
img.title = "黄果短剧 App 下载二维码";
img.width = size;
img.height = size;
var canvas = encodeQRCanvas(text, size);
if (canvas) {
try {
img.src = canvas.toDataURL("image/png");
el.appendChild(img);
return true;
} catch (e) {
el.appendChild(canvas);
return true;
}
}
img.src =
"https://api.qrserver.com/v1/create-qr-code/?size=" +
size +
"x" +
size +
"&margin=0&data=" +
encodeURIComponent(text);
el.appendChild(img);
return true;
}
function syncDownloadUI(force) {
var url = getAppURL();
if (!url) return;
if (force || !qrReady) {
var pcOk = renderQR(pcQRBox, url, 164);
var h5Ok = renderQR(h5QRBox, url, 164);
qrReady = !!(pcOk || h5Ok);
}
if (h5URLEl) {
h5URLEl.textContent = "官方网址 " + url;
if (isHTTPURL(url)) {
h5URLEl.href = url;
h5URLEl.removeAttribute("aria-disabled");
} else {
h5URLEl.href = "#";
h5URLEl.setAttribute("aria-disabled", "true");
}
}
if (downloadCTA) {
downloadCTA.href = isHTTPURL(url) ? url : "#";
downloadCTA.toggleAttribute("aria-disabled", !isHTTPURL(url));
}
}
function openDialog(event) {
if (event) event.preventDefault();
mask.classList.add("is-open");
document.body.style.overflow = "hidden";
loadQRCodeLib()
.catch(function () { /* fallback image QR still works */ })
.then(function () {
requestAnimationFrame(function () {
requestAnimationFrame(function () {
syncDownloadUI(true);
});
});
});
}
function closeDialog() {
mask.classList.remove("is-open");
document.body.style.overflow = "";
}
function setPlatform(platform) {
if (platform !== "ios" && platform !== "android") return;
currentPlatform = platform;
platformBtns.forEach(function (btn) {
btn.classList.toggle(
"is-active",
btn.getAttribute("data-download-platform") === platform
);
});
if (copyBtn) {
copyBtn.textContent = "复制下载链接";
copyBtn.classList.remove("is-copied");
}
}
function copyLink() {
var url = getAppURL();
if (!url || !copyBtn) return;
function onSuccess() {
copyBtn.textContent = "已复制";
copyBtn.classList.add("is-copied");
if (copyTimer) clearTimeout(copyTimer);
copyTimer = setTimeout(function () {
copyBtn.textContent = "复制下载链接";
copyBtn.classList.remove("is-copied");
}, 1800);
}
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(url).then(onSuccess).catch(function () {
fallbackCopy(url, onSuccess);
});
return;
}
fallbackCopy(url, onSuccess);
}
function fallbackCopy(text, onSuccess) {
var input = document.createElement("input");
input.value = text;
input.setAttribute("readonly", "");
input.style.position = "fixed";
input.style.left = "-9999px";
document.body.appendChild(input);
input.select();
try {
document.execCommand("copy");
onSuccess();
} catch (e) {
/* ignore */
}
document.body.removeChild(input);
}
document.addEventListener("click", function (event) {
var openTrigger = event.target.closest("[data-download-app-open]");
if (openTrigger) {
// 移动端由带 appAddr 的原生链接直接跳转,不展示二维码弹窗。
if (isMobileViewport()) return;
openDialog(event);
return;
}
if (event.target.closest("[data-download-app-close]")) {
closeDialog();
return;
}
if (event.target === mask) {
closeDialog();
return;
}
var platformBtn = event.target.closest("[data-download-platform]");
if (platformBtn && mask.contains(platformBtn)) {
setPlatform(platformBtn.getAttribute("data-download-platform"));
return;
}
if (event.target.closest("[data-download-copy]")) {
copyLink();
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && mask.classList.contains("is-open")) {
closeDialog();
}
});
window.openDownloadAppDialog = openDialog;
window.closeDownloadAppDialog = closeDialog;
})();