/** * 账户资料编辑与新建工作区共用的客户端对话框。保存后通过回调更新宿主目录/资料,再关闭; * demo分支只构造本地结果,真实分支走profile PATCH或workspaces POST,不由组件直接操作canvas runtime。 */ "use client"; import { useState, type FormEvent } from "react"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { api, errorText, type Profile } from "@/lib/api"; import type { Workspace } from "@/lib/workspace"; import { UserAvatar } from "./user-avatar"; import styles from "./workspace.module.css"; /** mode决定表单,busy控制当前提交和退出,error用于就地反馈;输入默认值来自打开时profile。 */ export function AccountPanel({ mode, profile, demo, onClose, onProfile, onWorkspace }: { mode: "settings" | "workspace"; profile: Profile; demo: boolean; onClose: () => void; onProfile: (profile: Profile) => void; onWorkspace: (workspace: Workspace) => void; }) { const [busy, setBusy] = useState(false); const [error, setError] = useState(""); const settings = mode === "settings"; const name = profile.display_name || profile.username; /** 阻止原生导航,捕获FormData后提交;成功先通知宿主再onClose,失败显示错误并恢复按钮。 * HTML输入限制是交互提示,服务端仍校验真实资料/空间名称。 */ async function submit(event: FormEvent) { event.preventDefault(); if (busy) return; const data = new FormData(event.currentTarget); setBusy(true); setError(""); try { // 设置模式只提交display_name/username,避免将整个profile(含只读信息)作为修改payload。 if (settings) { const input = { display_name: String(data.get("display_name")).trim(), username: String(data.get("username")).trim() }; const updated = demo ? { ...profile, ...input } : await api("profile", { method: "PATCH", body: JSON.stringify(input) }); onProfile(updated); } else { const name = String(data.get("name")).trim(); const created = demo ? { id: crypto.randomUUID(), name, role: "admin" as const } : await api("workspaces", { method: "POST", body: JSON.stringify({ name }) }); onWorkspace(created); } onClose(); } catch (e) { setError(errorText(e)); } finally { setBusy(false); } } // 保存中禁用取消/提交,并拒绝Dialog的关闭状态变化;请求未结束不假装已成功关闭。 return ( { if (!open && !busy) onClose(); }}> {settings ? "账户设置" : "新建工作空间"} {settings ? "管理你的个人资料。" : "为相关的图谱和资料创建一个空间。"}
{settings ? ( <>
{profile.email || profile.username}
) : } {error &&

{error}

}
); }