diff --git a/docs/sections-inventory.md b/docs/sections-inventory.md index 48985f746..9029f0812 100644 --- a/docs/sections-inventory.md +++ b/docs/sections-inventory.md @@ -27,7 +27,7 @@ |---|------|------|------| | G1 | 顶部导航 Header(含 mega menu、语言切换) | ✅ v0.10.3 | `Header.tsx` | | G2 | 页脚 Footer(原站 elementor_library post 58) | ✅ v0.10.19 | `Footer.tsx`(ElementorRenderer 直出 46d7afa/d834160/28c7f0b8/a428bb4 + menu-2 移动菜单 + gtranslate 下拉) | -| G3 | 询价弹窗/表单 | 🟡 | `InquiryForm.tsx` | +| G3 | 询价弹窗/表单(原站 Elementor popup 1129 + CF7 表单 604) | ✅ v0.10.20 | `InquiryPopup.tsx`(全局监听 popup 链接 + 弹窗 DOM + 表单提交入库) | ## 三、首页版块清单(自上而下,20 版块) @@ -130,6 +130,17 @@ cookie-policy:19 段纯文本。 > 下拉 202×39 全部全等;390 实测逐项全等(56/15/347/337/97/46.4/61)。 > 注意:原站 headless 下 WP Rocket 延迟加载 Elementor/jQuery,JS 组件(tabs/swiper)默认不初始化, > 比对该类版块需先 `page.mouse.wheel` 或按线上真实状态换算,勿把"未初始化"当基线。 +> +> **G3 询价弹窗取证(v0.10.20)**:全站 24 处 “Make an Inquiry”/按钮均为 +> `#elementor-action:action=popup:open&settings={"id":"1129"}`(base64),对应 popup 1129, +> 内含 EAEL Contact Form 7(表单 604:Name/Company/Business email/Phone/Product/Interest/ +> Annual Demand/Message + acceptance + reCAPTCHA 声明)。实现为全局 `InquiryPopup`: +> 文档级委托点击 → 渲染 Elementor 弹窗 DOM(遮罩 rgba(0,0,0,.8)、700px 白卡、close 20/20), +> 表单样式按 popup 生成 CSS(padding 2em 3em、字段 48%/31.3%、#C9CEE8 边框、textarea 134px、 +> 按钮 #ED6C00→#FFA11B、圆角 10)与 EAEL 默认(input 8px 16px/高 42),提交走 submitInquiry +> (form_key=contact-form-1),成功显示 CF7 原文提示;弹窗内社交图标 5 个(20px/间距 14/品牌色)。 +> 实测 1436:白卡 700×737 居中、两列 289.9/三列 189、消息框 604×153;390:宽 390、p5/p6 两列、 +> p7 全宽,与 popup 自定义 CSS 一致;提交入库验证后已清理测试数据。 ## 七、已知遗留(非当前版块范围,后续版块收口) diff --git a/package.json b/package.json index 3f2ac666c..e0f93ff67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dusuniot-rebuild", - "version": "0.10.19", + "version": "0.10.20", "private": true, "type": "module", "scripts": { diff --git a/src/components/website/InquiryPopup.tsx b/src/components/website/InquiryPopup.tsx new file mode 100644 index 000000000..66cdc9bf7 --- /dev/null +++ b/src/components/website/InquiryPopup.tsx @@ -0,0 +1,301 @@ +/** + * # 组件 询价弹窗 InquiryPopup(原站 Elementor popup 1129 + CF7 表单 604) + * 原站首页/方案页等 24 处 “Make an Inquiry” / 按钮均指向 + * `#elementor-action%3Aaction%3Dpopup%3Aopen%26settings%3D...` 的 popup 1129, + * 由 Elementor Pro 弹窗 DOM(.elementor-popup-modal + .dialog-*)承载 EAEL Contact Form 7。 + * 本站改为预渲染弹窗(首屏不加载,点击时才挂载),表单直接提交 submitInquiry。 + * 表单字段/文案/样式取自: + * - popup 1129 的 _elementor_data(标题 CONTACT US、内边距 2em 3em、textarea 134px 等) + * - CF7 表单 604 的 post_content(Name/Company/Email/Phone/Product/Interest/AnnualDemand/Message + * + acceptance 勾选 + reCAPTCHA 声明 + Submit) + * - popup 1129 生成 CSS(字段 48%/31.3% 两列三列布局、边框 #C9CEE8、按钮 #ED6C00→#FFA11B) + */ +import { useEffect, useRef, useState, type FormEvent } from "react"; +import { submitInquiry } from "~/server/inquiries"; + +/** # 常量 展开的弹窗 id(原站 popup 1129) **/ +const POPUP_ID = "1129"; + +/** # 常量 弹窗社交图标(popup 内 social-icons widget:20px/间距 14/官方品牌色) **/ +const POPUP_SOCIALS = [ + { icon: "fa-linkedin", label: "LinkedIn", href: "https://www.linkedin.com/company/dusun-electron-ltd/", color: "#0077B5" }, + { icon: "fa-youtube", label: "YouTube", href: "https://www.youtube.com/channel/UCyb4PpqVgvKgC9KpkByZaaQ", color: "#CD201F" }, + { icon: "fa-tiktok", label: "TikTok", href: "https://www.tiktok.com/@dusun_iot", color: "#000000" }, + { icon: "fa-facebook", label: "Facebook", href: "https://www.facebook.com/DUSUN-IoT-101398069457701", color: "#3B5998" }, + { icon: "fa-twitter", label: "Twitter", href: "https://twitter.com/Dusunelectron", color: "#1DA1F2" }, +]; + +/** # 常量 产品线下拉(CF7 表单 604 原文) **/ +const PRODUCT_OPTIONS = ["IoT Gateway", "System on Module", "Development Board", "Remote Control", "Voice Recognition Module", "Control Board", "Beacon & Sensor", "Other"]; +/** # 常量 合作意向下拉 **/ +const INTEREST_OPTIONS = ["Sales", "Distribution", "ODM", "OEM", "Technical support", "Other"]; +/** # 常量 年需求量下拉 **/ +const DEMAND_OPTIONS = ["1-50", "51-200", "201-1000", "1001-5000", "5000+"]; + +/** # 组件 询价弹窗(全局挂载于 Layout,监听 Elementor popup 链接) */ +export function InquiryPopup() { + const [open, setOpen] = useState(false); + const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle"); + const [errorMsg, setErrorMsg] = useState(""); + const formRef = useRef(null); + + // 全局委托:拦截任意指向 popup 1129 的 Elementor 动作链接 + useEffect(() => { + const onClick = (e: MouseEvent) => { + const a = (e.target as HTMLElement | null)?.closest?.("a[href*='elementor-action']") as HTMLAnchorElement | null; + if (!a) return; + const href = a.getAttribute("href") || ""; + if (!href.includes("popup%3Aopen")) return; + const m = /settings%3D([A-Za-z0-9%_=-]+)/.exec(href); + let id = ""; + if (m) { + try { + id = String(JSON.parse(atob(decodeURIComponent(m[1]!))).id || ""); + } catch { + id = ""; + } + } + if (id !== POPUP_ID) return; + e.preventDefault(); + setStatus("idle"); + setErrorMsg(""); + setOpen(true); + }; + document.addEventListener("click", onClick); + return () => document.removeEventListener("click", onClick); + }, []); + + // 打开时锁定页面滚动 + Esc 关闭(原站 dialog-prevent-scroll 行为) + useEffect(() => { + if (!open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") setOpen(false); + }; + document.addEventListener("keydown", onKey); + document.body.classList.add("dialog-prevent-scroll"); + return () => { + document.removeEventListener("keydown", onKey); + document.body.classList.remove("dialog-prevent-scroll"); + }; + }, [open]); + + if (!open) return null; + + /** # 函数 表单提交:映射到 submitInquiry(form_key=contact-form-1,legacy 604) */ + async function handleSubmit(e: FormEvent) { + e.preventDefault(); + const fd = new FormData(e.currentTarget); + setStatus("submitting"); + setErrorMsg(""); + try { + const res = await submitInquiry({ + data: { + formKey: "contact-form-1", + name: String(fd.get("your-name") || ""), + email: String(fd.get("your-email") || ""), + phone: String(fd.get("Phone") || ""), + company: String(fd.get("Company") || ""), + country: "", + message: String(fd.get("your-message") || ""), + productInterest: String(fd.get("Product") || ""), + _gotcha: String(fd.get("_gotcha") || ""), + extra: { + interest: String(fd.get("Interest") || ""), + annualdemand: String(fd.get("AnnualDemand") || ""), + consent: fd.get("acceptance-918") ? "1" : "", + }, + }, + }); + if (res.ok) { + setStatus("success"); + formRef.current?.reset(); + } else { + setStatus("error"); + setErrorMsg(res.error || "提交失败,请稍后重试"); + } + } catch (err) { + setStatus("error"); + setErrorMsg(err instanceof Error ? err.message : "网络异常,请稍后重试"); + } + } + + return ( +