's'调试支付
This commit is contained in:
@@ -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("");
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
Reference in New Issue
Block a user