import { useState } from 'react'; import { useSaaSStore } from '../../store/saasStore'; import { SaaSLogin } from './SaaSLogin'; import { SaaSStatus } from './SaaSStatus'; import { Cloud, Info, KeyRound } from 'lucide-react'; import { saasClient } from '../../lib/saas-client'; export function SaaSSettings() { const isLoggedIn = useSaaSStore((s) => s.isLoggedIn); const account = useSaaSStore((s) => s.account); const saasUrl = useSaaSStore((s) => s.saasUrl); const connectionMode = useSaaSStore((s) => s.connectionMode); const login = useSaaSStore((s) => s.login); const register = useSaaSStore((s) => s.register); const logout = useSaaSStore((s) => s.logout); const [showLogin, setShowLogin] = useState(!isLoggedIn); const [loginError, setLoginError] = useState(null); const [isLoggingIn, setIsLoggingIn] = useState(false); const handleLogin = async (url: string, username: string, password: string) => { setIsLoggingIn(true); setLoginError(null); try { await login(url, username, password); setShowLogin(false); } catch (err: unknown) { const message = err instanceof Error ? err.message : '登录失败'; setLoginError(message); } finally { setIsLoggingIn(false); } }; const handleRegister = async ( url: string, username: string, email: string, password: string, displayName?: string, ) => { setIsLoggingIn(true); setLoginError(null); try { await register(url, username, email, password, displayName); // register auto-logs in, no need for separate login call setShowLogin(false); } catch (err: unknown) { const message = err instanceof Error ? err.message : '注册失败'; setLoginError(message); } finally { setIsLoggingIn(false); } }; const handleLogout = () => { logout(); setShowLogin(true); setLoginError(null); }; return (

SaaS 账号

管理 ZCLAW 云端平台连接

{/* Connection mode info */}
当前模式: {connectionMode === 'saas' ? 'SaaS 云端' : connectionMode === 'gateway' ? 'Gateway' : '本地 Tauri'}。 {connectionMode !== 'saas' && '连接 SaaS 平台可解锁云端同步、团队协作等高级功能。'}
{/* Login form or status display */} {!showLogin ? ( setShowLogin(true)} /> ) : ( )} {/* Features list when logged in */} {isLoggedIn && !showLogin && (

云端功能

)} {/* Password change section */} {isLoggedIn && !showLogin && }
); } function CloudFeatureRow({ name, description, status, }: { name: string; description: string; status: 'active' | 'inactive'; }) { return (
{name}
{description}
{status === 'active' ? '可用' : '需要订阅'}
); } function ChangePasswordSection() { const [isOpen, setIsOpen] = useState(false); const [oldPassword, setOldPassword] = useState(''); const [newPassword, setNewPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); setSuccess(false); if (newPassword.length < 8) { setError('新密码至少 8 个字符'); return; } if (newPassword !== confirmPassword) { setError('两次输入的新密码不一致'); return; } setIsSubmitting(true); try { await saasClient.changePassword(oldPassword, newPassword); setSuccess(true); setOldPassword(''); setNewPassword(''); setConfirmPassword(''); } catch (err: unknown) { const message = err instanceof Error ? err.message : '密码修改失败'; setError(message); } finally { setIsSubmitting(false); } }; return (
setIsOpen(!isOpen)} >

账号安全

{isOpen ? '收起' : '展开'}
{isOpen && (
修改密码
setOldPassword(e.target.value)} required className="w-full px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-transparent" />
setNewPassword(e.target.value)} required minLength={8} className="w-full px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-transparent" />
setConfirmPassword(e.target.value)} required minLength={8} className="w-full px-3 py-2 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-transparent" />
{error && (

{error}

)} {success && (

密码修改成功

)}
)}
); }