's'
This commit is contained in:
@@ -180,6 +180,8 @@ export default function HomeClient() {
|
||||
() => readVipBootstrapState().userEmail
|
||||
);
|
||||
const [payPendingOrderId, setPayPendingOrderId] = useState<string | null>(null);
|
||||
const [wechatNick, setWechatNick] = useState<string | null>(null);
|
||||
const [wechatAvatar, setWechatAvatar] = useState<string | null>(null);
|
||||
|
||||
const savePaidType = useCallback((type: string | null) => {
|
||||
if (type) setStorage("paidType", type);
|
||||
@@ -192,6 +194,110 @@ export default function HomeClient() {
|
||||
setUserName(name);
|
||||
}, []);
|
||||
|
||||
const recoverAnonymousUserId = useCallback(
|
||||
async (params: { userId?: string; email?: string; wechatUserId?: string }) => {
|
||||
const payload: Record<string, string> = {};
|
||||
if (params.userId?.trim()) payload.user_id = params.userId.trim();
|
||||
if (params.email?.trim()) payload.email = params.email.trim().toLowerCase();
|
||||
if (params.wechatUserId?.trim()) payload.wechat_userid = params.wechatUserId.trim();
|
||||
if (!payload.user_id && !payload.email && !payload.wechat_userid) return null;
|
||||
|
||||
try {
|
||||
const res = await fetch("/api/vip/identity-diagnose", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
credentials: "same-origin",
|
||||
cache: "no-store",
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
const candidate = [
|
||||
data?.resolved?.linked_anonymous_user_id,
|
||||
data?.vip_email_link?.by_anonymous_user_id?.anonymous_user_id,
|
||||
data?.vip_email_link?.by_email?.anonymous_user_id,
|
||||
data?.payments?.by_user_id?.user_id,
|
||||
data?.payments?.by_linked_user_id?.user_id,
|
||||
].find((x) => typeof x === "string" && /^user\d+$/.test(x.trim()));
|
||||
return typeof candidate === "string" ? candidate.trim() : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const syncWechatProfile = useCallback(async () => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const urlWechatUserId =
|
||||
params.get("userid")?.trim() ||
|
||||
params.get("wechat_userid")?.trim() ||
|
||||
"";
|
||||
if (urlWechatUserId) {
|
||||
// 兼容历史字段:userid(微信私信真实用户ID)
|
||||
setStorage("userid", urlWechatUserId);
|
||||
setStorage("wechatUserId", urlWechatUserId);
|
||||
// 安全要求:落本地后立即去掉 URL 中敏感 userid 参数,避免被转发扩散
|
||||
const cleanPath = window.location.pathname || "/";
|
||||
window.location.replace(cleanPath);
|
||||
return;
|
||||
}
|
||||
const wechatUserId =
|
||||
(getStorage("wechatUserId") || "").trim() ||
|
||||
(getStorage("userid") || "").trim();
|
||||
if (!wechatUserId) return;
|
||||
|
||||
const userId = getStorage("userId") || "";
|
||||
const userEmail = (getStorage("userEmail") || "").trim().toLowerCase();
|
||||
try {
|
||||
const res = await fetch("/api/vip/wechat-profile", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
user_id: userId || undefined,
|
||||
email: userEmail || undefined,
|
||||
userid: wechatUserId,
|
||||
wechat_userid: wechatUserId,
|
||||
}),
|
||||
credentials: "same-origin",
|
||||
cache: "no-store",
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
const profile = data?.profile || null;
|
||||
const relations = data?.relations || null;
|
||||
const nickname =
|
||||
typeof profile?.nickname === "string" ? profile.nickname.trim() : "";
|
||||
const avatar =
|
||||
typeof profile?.avatar === "string" ? profile.avatar.trim() : "";
|
||||
const linkedAnonymousUserId =
|
||||
typeof relations?.linked_anonymous_user_id === "string"
|
||||
? relations.linked_anonymous_user_id.trim()
|
||||
: typeof relations?.anonymous_user_id === "string"
|
||||
? relations.anonymous_user_id.trim()
|
||||
: "";
|
||||
if (/^user\d+$/.test(linkedAnonymousUserId)) {
|
||||
setStorage("userId", linkedAnonymousUserId);
|
||||
setStorage("memosAccount", linkedAnonymousUserId);
|
||||
setAnonymousUserCookie(linkedAnonymousUserId);
|
||||
}
|
||||
if (nickname) {
|
||||
setWechatNick(nickname);
|
||||
setStorage("wechatNick", nickname);
|
||||
} else {
|
||||
setWechatNick(null);
|
||||
removeStorage("wechatNick");
|
||||
}
|
||||
if (avatar) {
|
||||
setWechatAvatar(avatar);
|
||||
setStorage("wechatAvatar", avatar);
|
||||
} else {
|
||||
setWechatAvatar(null);
|
||||
removeStorage("wechatAvatar");
|
||||
}
|
||||
} catch {
|
||||
// 忽略失败,不影响主流程
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getStoredAnonymousUserId = useCallback((): string | null => {
|
||||
const memosAccount = getStorage("memosAccount");
|
||||
if (memosAccount && /^user\d+$/.test(memosAccount)) {
|
||||
@@ -278,6 +384,9 @@ export default function HomeClient() {
|
||||
): Promise<{ ok: boolean; error?: string }> => {
|
||||
try {
|
||||
const normalizedEmail = email.trim().toLowerCase();
|
||||
const wechatUserId =
|
||||
(getStorage("wechatUserId") || "").trim() ||
|
||||
(getStorage("userid") || "").trim();
|
||||
const res = await fetch("/api/vip/check-by-email", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -285,6 +394,7 @@ export default function HomeClient() {
|
||||
email: normalizedEmail,
|
||||
password,
|
||||
...(user_id?.trim() && { user_id: user_id.trim() }),
|
||||
...(wechatUserId && { wechat_userid: wechatUserId }),
|
||||
}),
|
||||
credentials: "include",
|
||||
});
|
||||
@@ -523,6 +633,14 @@ export default function HomeClient() {
|
||||
isH5 ? payPendingOrderId ?? undefined : undefined
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const nick = getStorage("wechatNick");
|
||||
const avatar = getStorage("wechatAvatar");
|
||||
if (nick) setWechatNick(nick);
|
||||
if (avatar) setWechatAvatar(avatar);
|
||||
void syncWechatProfile();
|
||||
}, [syncWechatProfile]);
|
||||
|
||||
useEffect(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.get("type")?.trim() === "clean") {
|
||||
@@ -583,7 +701,23 @@ export default function HomeClient() {
|
||||
}
|
||||
|
||||
// 校验逻辑:有本地存储(登录资料+VIP)时优先使用并校验;无身份/VIP 时点击按钮直接进入支付,不校验
|
||||
const anonymousCandidate = getStoredAnonymousUserId();
|
||||
const wechatUserId =
|
||||
(getStorage("wechatUserId") || "").trim() ||
|
||||
(getStorage("userid") || "").trim();
|
||||
let anonymousCandidate = getStoredAnonymousUserId();
|
||||
if (!anonymousCandidate && wechatUserId) {
|
||||
const recoveredFromWechat = await recoverAnonymousUserId({
|
||||
wechatUserId,
|
||||
email: (getStorage("userEmail") || "").trim().toLowerCase(),
|
||||
userId: (getStorage("userId") || "").trim(),
|
||||
});
|
||||
if (recoveredFromWechat && /^user\d+$/.test(recoveredFromWechat)) {
|
||||
anonymousCandidate = recoveredFromWechat;
|
||||
setStorage("userId", recoveredFromWechat);
|
||||
setStorage("memosAccount", recoveredFromWechat);
|
||||
setAnonymousUserCookie(recoveredFromWechat);
|
||||
}
|
||||
}
|
||||
const hadStoredUserId = !!anonymousCandidate;
|
||||
const emailVerifiedAt = Number(getStorage(EMAIL_VERIFY_TS_KEY) || "0");
|
||||
const skipAnonymousRecover =
|
||||
@@ -634,7 +768,28 @@ export default function HomeClient() {
|
||||
) {
|
||||
setStorage("memosAccount", meData.user.anonymousUserId);
|
||||
}
|
||||
setStorage("userId", meData.user.id);
|
||||
const wechatUserId =
|
||||
(getStorage("wechatUserId") || "").trim() ||
|
||||
(getStorage("userid") || "").trim();
|
||||
const recoveredAnonymousUserId =
|
||||
(cur && /^user\d+$/.test(cur) ? cur : "") ||
|
||||
(typeof meData.user.anonymousUserId === "string" &&
|
||||
/^user\d+$/.test(meData.user.anonymousUserId)
|
||||
? meData.user.anonymousUserId.trim()
|
||||
: "") ||
|
||||
((await recoverAnonymousUserId({
|
||||
userId: cur || meData.user.id || "",
|
||||
email: meData.user.email || "",
|
||||
wechatUserId,
|
||||
})) ||
|
||||
"");
|
||||
if (/^user\d+$/.test(recoveredAnonymousUserId)) {
|
||||
setStorage("userId", recoveredAnonymousUserId);
|
||||
setStorage("memosAccount", recoveredAnonymousUserId);
|
||||
setAnonymousUserCookie(recoveredAnonymousUserId);
|
||||
} else {
|
||||
setStorage("userId", meData.user.id);
|
||||
}
|
||||
setStorage("emailLinked", "1");
|
||||
if (meData.user.email) {
|
||||
setStorage("userEmail", meData.user.email);
|
||||
@@ -667,6 +822,7 @@ export default function HomeClient() {
|
||||
getOrCreateUserId,
|
||||
getStoredAnonymousUserId,
|
||||
checkPaymentFromPB,
|
||||
recoverAnonymousUserId,
|
||||
savePaidType,
|
||||
saveUserName,
|
||||
tryRecoverByAnonymousUserId,
|
||||
@@ -734,7 +890,14 @@ export default function HomeClient() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<VipLayout isLoggedIn={isLoggedIn} userName={userName} userEmail={userEmail} onLogout={handleLogout}>
|
||||
<VipLayout
|
||||
isLoggedIn={isLoggedIn}
|
||||
userName={userName}
|
||||
userEmail={userEmail}
|
||||
wechatNick={wechatNick}
|
||||
wechatAvatar={wechatAvatar}
|
||||
onLogout={handleLogout}
|
||||
>
|
||||
{isLoggedIn ? (
|
||||
<DashboardPage userName={userName} userEmail={userEmail} />
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user