文件已经写好,这是纯本地版的完整 HTML,双击打开就能用。文件在 [index.html](file:///workspace/index.html)。 下面是完整代码,你可以直接全选复制保存为 `index.html`: ```html 今日吃啥 · 食谱小站

联系网页发布者

制作同款

`; var form = root.querySelector("form"); root.querySelector("h2").textContent = config.form.title; var customFields = []; (config.form.fields || []).forEach(function (field) { var label = document.createElement("label"); label.textContent = field.label + (field.required ? "" : "(选填)"); var input = document.createElement("input"); input.name = field.key;input.maxLength = 500;input.required = field.required; label.appendChild(input);form.insertBefore(label, form.querySelector(".consent"));customFields.push(field.key); }); var trap = document.createElement("input");trap.name = "website";trap.autocomplete = "off";trap.tabIndex = -1;trap.setAttribute("aria-hidden","true"); trap.style.cssText = "position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;";form.appendChild(trap); var button = form.querySelector("button"); var status = root.querySelector(".status"); var launcher = root.querySelector(".launcher"); var dialog = root.querySelector("dialog"); var close = root.querySelector(".close"); form.action = config.endpoint; root.querySelector(".remake").href = config.home; var sending = false; var submitted = false; function openDialog() { if (dialog.open) return; dialog.showModal();launcher.setAttribute("aria-expanded","true"); (submitted ? close : form.elements.email).focus({preventScroll:true}); } launcher.addEventListener("click", openDialog); close.addEventListener("click", function () { dialog.close(); }); dialog.addEventListener("close", function () { if (dialog.open) return; launcher.setAttribute("aria-expanded","false");launcher.focus({preventScroll:true}); }); dialog.addEventListener("click", function (event) { if (event.target !== dialog) return; var box = dialog.getBoundingClientRect(); if (event.clientX < box.left || event.clientX > box.right || event.clientY < box.top || event.clientY > box.bottom) dialog.close(); }); dialog.addEventListener("keydown", function (event) { if (event.key !== "Tab") return; var controls = Array.prototype.filter.call(dialog.querySelectorAll("button,input,textarea,select,a[href],[tabindex]"), function (control) { return !control.disabled && control.tabIndex >= 0 && control.getClientRects().length; }); if (!controls.length) return; var index = controls.indexOf(root.activeElement); var next = index < 0 ? (event.shiftKey ? controls.length - 1 : 0) : (index + (event.shiftKey ? -1 : 1) + controls.length) % controls.length; event.preventDefault();controls[next].focus(); }); // Isolate widget actions but let page drags finish over the closed launcher. ["click","dblclick","contextmenu","pointerdown","pointerup","pointermove","mousedown","mouseup","mousemove","touchstart","touchmove","touchend","keydown","keyup","wheel"].forEach(function (name) { root.addEventListener(name, function (event) { if (dialog.open || ["click","dblclick","contextmenu","pointerdown","mousedown","touchstart","keydown","keyup"].indexOf(name) !== -1) event.stopPropagation(); }); }); function followLink(event) { if (event.defaultPrevented || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return; var link = event.target && event.target.closest ? event.target.closest("a[href]") : null; if (!link || link.hasAttribute("download") || link.target === "_blank") return; try { var url = new URL(link.href, location.href); if (url.origin === location.origin && url.pathname === location.pathname && url.hash === "#" + host.id) { event.preventDefault();openDialog(); } } catch (error) {} } var positionFrame = 0; var agentRoots = []; function positionLauncher() { positionFrame = 0; if (!host.isConnected) return; var viewport = window.visualViewport; var width = viewport ? viewport.width : innerWidth; var height = viewport ? viewport.height : innerHeight; var top = viewport ? viewport.offsetTop : 0; var left = viewport ? viewport.offsetLeft : 0; var obstacles = []; document.querySelectorAll("[data-bz-agent-embed],[data-bz-edit-entry]").forEach(function (node) { if (node.shadowRoot) { node.shadowRoot.querySelectorAll(".launcher,.floating-panel.open,.full-panel").forEach(function (control) { var box = control.getBoundingClientRect(); if (box.width && box.height) obstacles.push(box); }); } else { var box = node.getBoundingClientRect();if (box.width && box.height) obstacles.push(box); } }); var middle = top + height / 2 - 22; var upper = top + Math.max(12, height * .18); var candidates = [[left + width - 56,middle],[left + width - 56,upper],[left + 12,middle],[left + 12,upper]]; var position = candidates.find(function (point) { return !obstacles.some(function (box) { return point[0] < box.right + 8 && point[0] + 44 > box.left - 8 && point[1] < box.bottom + 8 && point[1] + 44 > box.top - 8; }); }); launcher.hidden = !position; if (position) { host.style.setProperty("--bz-lead-left", position[0] + "px");host.style.setProperty("--bz-lead-top", position[1] + "px"); } dialog.style.setProperty("--bz-dialog-top", top + height / 2 + "px"); dialog.style.setProperty("--bz-dialog-height", Math.max(140, height - 24) + "px"); } function schedulePosition() { if (!positionFrame) positionFrame = requestAnimationFrame(positionLauncher); } document.body.appendChild(host); document.querySelectorAll("[data-bz-agent-embed]").forEach(function (node) { if (node.shadowRoot) { agentRoots.push(node.shadowRoot);node.shadowRoot.addEventListener("click", schedulePosition); } }); window.addEventListener("resize", schedulePosition); if (window.visualViewport) { visualViewport.addEventListener("resize", schedulePosition);visualViewport.addEventListener("scroll", schedulePosition); } document.addEventListener("click", followLink); host.__bzLeadCleanup = function () { if (positionFrame) cancelAnimationFrame(positionFrame); window.removeEventListener("resize", schedulePosition);document.removeEventListener("click", followLink); agentRoots.forEach(function (agentRoot) { agentRoot.removeEventListener("click", schedulePosition); }); if (window.visualViewport) { visualViewport.removeEventListener("resize", schedulePosition);visualViewport.removeEventListener("scroll", schedulePosition); } }; positionLauncher(); form.addEventListener("submit", async function (event) { event.preventDefault(); if (sending || submitted || !form.reportValidity()) return; sending = true;button.disabled = true;button.textContent = "正在提交"; status.textContent = "";status.removeAttribute("data-error");status.removeAttribute("data-success"); try { var fields = new FormData(form); var custom = {};customFields.forEach(function (key) { custom[key] = fields.get(key) || ""; }); var response = await fetch(config.endpoint, { method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"}, body:JSON.stringify({name:fields.get("name") || "",email:fields.get("email") || "",phone:fields.get("phone") || "",message:fields.get("message") || "",website:fields.get("website") || "",custom:custom}) }); var result = await response.json(); if (!response.ok || result.code !== 0 || !result.data || !result.data.submitted) throw new Error(result.message || "提交失败,请稍后重试"); submitted = true;status.setAttribute("data-success","1");status.textContent = "留言已提交";button.textContent = "已提交"; form.querySelectorAll("input,textarea").forEach(function (input) { input.disabled = true; }); } catch (error) { status.setAttribute("data-error","1");status.textContent = error.message || "网络异常,请稍后重试";button.textContent = "提交意向"; } finally { sending = false;button.disabled = submitted; } }); } if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", mount); else mount(); })();