"use client"; import { useCallback, useEffect, useRef, useState } from "react"; import Image from "next/image"; import { marked } from "marked"; import PocketBase from "pocketbase"; import { indexMd } from "./index-content"; import styles from "./index.module.css"; import { getPayEnv, getRecommendedChannel, mustUseWxPay, getDeviceFromEnv, } from "@/app/lib/payEnv"; import { usePayStatusPoll } from "@/app/lib/usePayStatusPoll"; const PB_URL = process.env.NEXT_PUBLIC_POCKETBASE_URL || "https://pocketbase.hackrobot.cn"; function redirectToPay(params: { user_id: string; return_url: string; total_fee: number; type: string; channel: "alipay" | "wxpay"; device: "pc" | "h5" | "wechat"; }) { const form = document.createElement("form"); form.method = "POST"; form.action = "/api/pay"; form.target = "_self"; form.style.display = "none"; const fields: [string, string][] = [ ["user_id", params.user_id], ["return_url", params.return_url], ["total_fee", String(params.total_fee)], ["type", params.type], ["channel", params.channel], ["device", params.device], ["html", "1"], ]; fields.forEach(([k, v]) => { const input = document.createElement("input"); input.type = "hidden"; input.name = k; input.value = v; form.appendChild(input); }); document.body.appendChild(form); form.submit(); } function getStorage(key: string): string | null { if (typeof window === "undefined") return null; return localStorage.getItem(key); } function setStorage(key: string, value: string): void { if (typeof window === "undefined") return; localStorage.setItem(key, value); } function removeStorage(key: string): void { if (typeof window === "undefined") return; localStorage.removeItem(key); } export default function Home() { const [paidType, setPaidType] = useState(null); const [userName, setUserName] = useState(null); const [loading, setLoading] = useState(true); const contentRef = useRef(null); const savePaidType = useCallback((type: string | null) => { if (type) setStorage("paidType", type); else removeStorage("paidType"); setPaidType(type); }, []); const saveUserName = useCallback((name: string) => { setStorage("userName", name); setUserName(name); }, []); const getOrCreateUserId = useCallback(() => { let userId = getStorage("userId"); if (!userId) { userId = `user${Date.now()}`; setStorage("userId", userId); } return userId; }, []); const checkPaymentFromPB = useCallback(async (userId: string) => { try { const pb = new PocketBase(PB_URL); const records = await pb.collection("payments").getList(1, 1, { filter: `user_id = "${userId}"`, sort: "-created", }); if (records.items.length > 0) { const latestType = records.items[0].type as string; const dbUserId = records.items[0].user_id as string; savePaidType(latestType); saveUserName(dbUserId); return latestType; } else { savePaidType(null); return null; } } catch (err) { console.error("查询 PocketBase 失败:", err); return getStorage("paidType"); } }, [savePaidType, saveUserName]); const clearAllStorage = useCallback(() => { try { if (typeof window !== "undefined" && window.localStorage) { window.localStorage.clear(); } removeStorage("userId"); removeStorage("paidType"); removeStorage("userName"); setPaidType(null); setUserName(null); setLoading(false); alert("本地存储已清空"); // 移除 URL 中的 ?type=clean,避免刷新时重复触发 if (typeof window !== "undefined" && window.history.replaceState) { window.history.replaceState({}, "", window.location.pathname); } } catch (error) { console.error("清空存储失败:", error); alert("清空存储失败"); } }, []); const handlePay = useCallback(() => { const userId = getOrCreateUserId(); const returnUrl = `${window.location.origin}/paid`; const env = getPayEnv(); const channel = mustUseWxPay(env) ? "wxpay" : getRecommendedChannel(env); const device = getDeviceFromEnv(env); redirectToPay({ user_id: userId, return_url: returnUrl, total_fee: 18800, type: "vip", channel, device, }); }, [getOrCreateUserId]); const handleCopyUsername = useCallback(() => { const name = userName || ""; if (typeof navigator !== "undefined" && navigator.clipboard) { navigator.clipboard.writeText(name); alert("账号已复制"); } }, [userName]); // 微信 H5 支付完成后可能不跳转,轮询检测到已支付则刷新 usePayStatusPoll(() => { savePaidType("vip"); saveUserName(getStorage("userId") || ""); }); useEffect(() => { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get("type") === "clean") { clearAllStorage(); return; } if (urlParams.get("paid") === "1") { savePaidType("vip"); saveUserName(getStorage("userId") || ""); } const init = async () => { getOrCreateUserId(); const localType = getStorage("paidType"); const localUserName = getStorage("userName"); if (localType && localUserName) { setPaidType(localType); setUserName(localUserName); setLoading(false); return; } const userId = getStorage("userId"); if (userId) { await checkPaymentFromPB(userId); } setLoading(false); }; init(); }, [clearAllStorage, getOrCreateUserId, checkPaymentFromPB, savePaidType, saveUserName]); marked.setOptions({ breaks: true, gfm: true }); return (
异度星球
group
数字游民社群
还在独自摸索吗?
{paidType === "vip" ? (
{ window.location.href = "https://qun.hackrobot.cn"; }} style={{ cursor: "pointer" }} > 👉星球地址: qun.hackrobot.cn
账号:{getStorage("userName")}
密码:123456
打开网页后,请点击"左上角头像",打开侧面栏
) : ( )}
avatar
laptop
无人直播
travel
RPA自动化
code
聊天机器人
); }