This commit is contained in:
eric
2026-03-27 18:20:36 -05:00
parent a8976b2eee
commit 326bad4336
34 changed files with 2787 additions and 996 deletions

View File

@@ -0,0 +1,133 @@
"use client";
import { useEffect, useState } from "react";
import { Copyable } from "../Copyable";
import styles from "../vip.module.css";
const COMMUNITY_URL = "https://qun.hackrobot.cn";
const DEFAULT_PASSWORD = "12345678";
function getStorage(key: string): string | null {
if (typeof window === "undefined") return null;
return localStorage.getItem(key);
}
function isAnonymousUserId(value: string | null): value is string {
return !!value && /^user\d+$/.test(value);
}
type CommunityAccessModalProps = {
open: boolean;
onClose: () => void;
};
/** 与 WelcomeBlock 同步的社群登录账号解析,用于弹窗展示 */
export function CommunityAccessModal({ open, onClose }: CommunityAccessModalProps) {
const userId = typeof window !== "undefined" ? getStorage("userId") : null;
const [backendMemosAccount, setBackendMemosAccount] = useState<string | null>(null);
const memosAccount =
getStorage("memosAccount") ||
backendMemosAccount ||
(isAnonymousUserId(userId) ? userId : null);
useEffect(() => {
if (!open || !userId) return;
fetch(`/api/vip/linked-email?user_id=${encodeURIComponent(userId)}`, {
cache: "no-store",
})
.then((res) => res.json())
.then((data) => {
const linkedAnonymousUserId =
typeof data?.anonymousUserId === "string" && /^user\d+$/.test(data.anonymousUserId)
? data.anonymousUserId
: null;
if (linkedAnonymousUserId && typeof window !== "undefined") {
setBackendMemosAccount(linkedAnonymousUserId);
localStorage.setItem("memosAccount", linkedAnonymousUserId);
}
})
.catch(() => {});
}, [open, userId]);
useEffect(() => {
if (!open) return;
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") onClose();
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
}, [open, onClose]);
if (!open) return null;
return (
<div
className={styles.communityModalBackdrop}
role="presentation"
onClick={onClose}
>
<div
className={styles.communityModalPanel}
role="dialog"
aria-modal="true"
aria-labelledby="community-modal-title"
onClick={(e) => e.stopPropagation()}
>
<div className={styles.communityModalGlow} aria-hidden />
<button
type="button"
className={styles.communityModalClose}
onClick={onClose}
aria-label="关闭"
>
×
</button>
<div className={styles.communityModalIconWrap}>
<span className={styles.communityModalIcon}>👥</span>
</div>
<h2 id="community-modal-title" className={styles.communityModalTitle}>
·
</h2>
<p className={styles.communityModalDesc}>
使访
</p>
<div className={styles.communityModalRows}>
<div className={styles.communityModalRow}>
<span className={styles.communityModalLabel}></span>
<div className={styles.communityModalValueWrap}>
<Copyable text={COMMUNITY_URL} className={styles.communityModalCopyable}>
<span className={styles.communityModalMono}>qun.hackrobot.cn</span>
</Copyable>
<a
href={COMMUNITY_URL}
target="_blank"
rel="noopener noreferrer"
className={styles.communityModalOpenLink}
>
</a>
</div>
</div>
<div className={styles.communityModalRow}>
<span className={styles.communityModalLabel}></span>
<Copyable text={memosAccount || ""} className={styles.communityModalCopyable}>
<span className={styles.communityModalMono}>{memosAccount || "—"}</span>
</Copyable>
</div>
<div className={styles.communityModalRow}>
<span className={styles.communityModalLabel}></span>
<Copyable text={DEFAULT_PASSWORD} className={styles.communityModalCopyable}>
<span className={styles.communityModalMono}>{DEFAULT_PASSWORD}</span>
</Copyable>
</div>
</div>
<button type="button" className={styles.communityModalDone} onClick={onClose}>
</button>
</div>
</div>
);
}