Files
web_hghl_h5/src/components/age-gate/age-gate-dialog.tsx
T
谢宇宁andClaude Opus 5.5 61d0a11dfa Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 17:51:31 +07:00

148 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useEffect, useSyncExternalStore } from "react";
import { useChromeless } from "@/components/layout/route-visibility";
/** 对齐 jha-1043 eightPop.js:sessionStorage + 关闭/退出均离开站点 */
const SESSION_KEY = "ageConfirmed";
const EXIT_URL = "about:blank";
let confirmed: boolean | null = null;
const listeners = new Set<() => void>();
function emit() {
listeners.forEach((listener) => listener());
}
function readConfirmed() {
if (confirmed === null) {
try {
confirmed = window.sessionStorage.getItem(SESSION_KEY) === "1";
} catch {
confirmed = false;
}
}
return confirmed;
}
function confirmAge() {
confirmed = true;
try {
window.sessionStorage.setItem(SESSION_KEY, "1");
} catch {
// sessionStorage 不可用时仍允许本页确认并关闭
}
emit();
}
export function openAgeGateDialog() {
confirmed = false;
try {
window.sessionStorage.removeItem(SESSION_KEY);
} catch {}
emit();
}
export function subscribeAgeGate(listener: () => void) {
listeners.add(listener);
return () => listeners.delete(listener);
}
export const getAgeGateOpen = () => !readConfirmed();
const getServerSnapshot = () => false;
function exitSite() {
try {
window.location.replace(EXIT_URL);
} catch {
window.location.href = EXIT_URL;
}
}
export function AgeGateDialogHost() {
const chromeless = useChromeless();
const open = useSyncExternalStore(subscribeAgeGate, getAgeGateOpen, getServerSnapshot) && !chromeless;
useEffect(() => {
if (!open) return;
const { overflow } = document.body.style;
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = overflow;
};
}, [open]);
if (!open) return null;
return (
<div data-component="age-gate-dialog" className="fixed inset-0 z-[60] flex flex-col items-center overflow-y-auto bg-black/70 px-4 py-10">
<div className="my-auto flex flex-col items-center gap-9 lg:gap-6">
<section
role="dialog"
aria-modal="true"
aria-labelledby="age-gate-title"
aria-describedby="age-gate-desc"
className="flex w-[300px] flex-col items-center gap-[18px] rounded-[20px] bg-[#0B0914] px-5 py-6 outline outline-1 outline-white/20 lg:w-[440px] lg:gap-9 lg:rounded-[40px] lg:p-9"
>
<AdultIcon />
<div className="flex flex-col gap-[18px] text-white/90 lg:gap-6">
<h2
id="age-gate-title"
className="text-center text-lg/6 font-semibold lg:text-2xl/8 lg:font-medium"
>
这是个成人网站
</h2>
<p id="age-gate-desc" className="text-justify text-sm/5 lg:text-lg/6">
本网站包含有年龄限制的内容,包括裸体和露骨色情素材的内容。
点击继续即表示您确认您已年满 18 岁,或在您访问本网站时所在的司法管辖区已是成年人
<span className="hidden lg:inline">。</span>
</p>
</div>
<div className="flex w-full flex-col gap-3">
<button
type="button"
onClick={confirmAge}
className="cursor-pointer rounded-xl bg-[#E9019C] py-[13px] text-base/[22px] font-semibold text-white transition hover:bg-[#F21AAA]"
>
我已年满18岁-进入
</button>
<button
type="button"
onClick={exitSite}
className="cursor-pointer rounded-xl bg-white/10 py-[13px] text-base/[22px] text-white/90 transition hover:bg-white/15"
>
我未满18岁-退出
</button>
</div>
</section>
<button type="button" aria-label="退出" onClick={exitSite} className="cursor-pointer size-9">
<svg viewBox="0 0 44 44" className="size-full" aria-hidden="true">
<circle cx="22" cy="22" r="21" fill="none" stroke="white" strokeWidth="2" />
<path d="M16 16l12 12M28 16L16 28" stroke="white" strokeWidth="2" strokeLinecap="round" />
</svg>
</button>
</div>
</div>
);
}
function AdultIcon() {
return (
<svg viewBox="0 0 78 78" className="size-[78px] shrink-0 text-[#E9019C]" aria-hidden="true">
<circle cx="39" cy="39" r="35" fill="none" stroke="currentColor" strokeWidth="5" />
<text
x="39"
y="40"
fill="currentColor"
fontSize="26"
fontWeight="800"
textAnchor="middle"
dominantBaseline="central"
fontFamily="Arial, Helvetica, sans-serif"
>
18+
</text>
</svg>
);
}