's'调试支付

This commit is contained in:
eric
2026-03-08 06:43:48 -05:00
parent b99fba1c5a
commit 1f4473cb04
35 changed files with 1794 additions and 178 deletions

View File

@@ -1,8 +1,11 @@
"use client";
import { useState, type FormEvent } from "react";
const PB_URL = process.env.NEXT_PUBLIC_POCKETBASE_URL || "https://pocketbase.hackrobot.cn";
import {
pbLogin,
pbRegister,
pbSaveAuth,
} from "@/app/lib/pocketbase";
interface AuthModalProps {
isOpen: boolean;
@@ -24,6 +27,7 @@ export default function AuthModal({ isOpen, onClose, onSuccess }: AuthModalProps
setLoading(true);
try {
let result;
if (mode === "register") {
if (password !== passwordConfirm) {
setError("两次密码不一致");
@@ -35,49 +39,11 @@ export default function AuthModal({ isOpen, onClose, onSuccess }: AuthModalProps
setLoading(false);
return;
}
const res = await fetch(`${PB_URL}/api/collections/users/records`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email,
password,
passwordConfirm,
}),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err?.message || "注册失败");
}
// 注册成功后自动登录
const authRes = await fetch(`${PB_URL}/api/collections/users/auth-with-password`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ identity: email, password }),
});
if (!authRes.ok) {
throw new Error("注册成功,请手动登录");
}
const authData = await authRes.json();
if (authData?.token) {
localStorage.setItem("pb_token", authData.token);
localStorage.setItem("pb_user", JSON.stringify(authData.record));
}
result = await pbRegister(email, password, passwordConfirm);
} else {
const res = await fetch(`${PB_URL}/api/collections/users/auth-with-password`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ identity: email, password }),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err?.message || "登录失败");
}
const data = await res.json();
if (data?.token) {
localStorage.setItem("pb_token", data.token);
localStorage.setItem("pb_user", JSON.stringify(data.record));
}
result = await pbLogin(email, password);
}
pbSaveAuth(result.token, result.record);
onSuccess(email);
onClose();
setEmail("");

View File

@@ -2,6 +2,7 @@
import { useState, useEffect } from "react";
import { Link, useLocale, usePathname, useRouter, useTranslation } from "@/i18n/navigation";
import { getStoredUserEmail, pbLogout } from "@/app/lib/pocketbase";
import AuthModal from "./AuthModal";
import ThemeToggle from "./ThemeToggle";
@@ -11,18 +12,6 @@ const navLinks = [
{ labelKey: "community" as const, href: "#community" },
];
function getStoredUser(): string | null {
if (typeof window === "undefined") return null;
try {
const raw = localStorage.getItem("pb_user");
if (!raw) return null;
const user = JSON.parse(raw);
return user?.email ?? null;
} catch {
return null;
}
}
export default function Header() {
const { t } = useTranslation("common");
const { t: tNav } = useTranslation("nav");
@@ -35,12 +24,11 @@ export default function Header() {
const [userEmail, setUserEmail] = useState<string | null>(null);
useEffect(() => {
setUserEmail(getStoredUser());
setUserEmail(getStoredUserEmail());
}, []);
const handleLogout = () => {
localStorage.removeItem("pb_token");
localStorage.removeItem("pb_user");
pbLogout();
setUserEmail(null);
};

View File

@@ -1,23 +1,19 @@
"use client";
import { useTranslation } from "@/i18n/navigation";
import toolsData from "../data/tools.json";
import type { ToolsCategory } from "@/app/lib/theme-data";
const categories = toolsData.categories as Array<{
icon: string;
title: string;
color: string;
bg: string;
text: string;
tools: Array<{ name: string; desc: string; href: string }>;
}>;
type ToolsProps = {
data: { categories: ToolsCategory[] };
};
function truncateDesc(desc: string, maxLen = 5) {
if (!desc || desc.length <= maxLen) return desc;
return desc.slice(0, maxLen) + "...";
}
export default function Tools() {
export default function Tools({ data }: ToolsProps) {
const categories = data.categories;
const { t } = useTranslation("tools");
const total = categories.reduce((s, c) => s + c.tools.length, 0);
const toolStats = [