/** * Phase 1: Redis 快取設定 * * 功能: * 1. 填寫 Redis 連接資訊 * 2. 測試 Redis 連接 * 3. 將設定寫入 .env 檔案 */ 'use client' import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' interface RedisConfig { host: string port: number password: string db: number } interface TestResult { success: boolean message: string redis_version?: string memory_usage?: string } export default function Phase1Redis() { const router = useRouter() const [config, setConfig] = useState({ host: '10.1.0.20', port: 6379, password: '', db: 0, }) const [testing, setTesting] = useState(false) const [testResult, setTestResult] = useState(null) const [setupPending, setSetupPending] = useState(false) const [loading, setLoading] = useState(true) const [alreadyConfigured, setAlreadyConfigured] = useState(false) // 載入已儲存的配置 useEffect(() => { loadSavedConfig() }, []) const loadSavedConfig = async () => { try { setLoading(true) const response = await fetch('http://10.1.0.245:10181/api/v1/installation/get-config/redis') if (!response.ok) { throw new Error(`HTTP ${response.status}`) } const data = await response.json() if (data.configured && data.config) { setConfig({ host: data.config.host || '10.1.0.20', port: parseInt(data.config.port) || 6379, password: data.config.password === '****' ? '' : (data.config.password || ''), db: parseInt(data.config.db) || 0, }) setAlreadyConfigured(true) } } catch (error) { console.error('[Redis] Failed to load saved config:', error) } finally { setLoading(false) } } const handleTest = async () => { try { setTesting(true) setTestResult(null) const response = await fetch('http://10.1.0.245:10181/api/v1/installation/test-redis', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config), }) const data = await response.json() if (!response.ok) { setTestResult({ success: false, message: data.detail || `HTTP ${response.status}`, }) return } setTestResult(data) if (data.success) { setSetupPending(true) } } catch (error) { setTestResult({ success: false, message: error instanceof Error ? error.message : '連接失敗', }) } finally { setTesting(false) } } const handleSetup = async () => { try { const response = await fetch('http://10.1.0.245:10181/api/v1/installation/setup-redis', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config), }) const data = await response.json() if (!response.ok) { alert(`設定失敗: ${data.detail}`) return } alert('Redis 設定成功!') router.push('/installation/phase2-database') } catch (error) { alert(`設定失敗: ${error instanceof Error ? error.message : '未知錯誤'}`) } } if (loading) { return (

載入已儲存的配置...

) } return (
{/* Progress Bar */}
進度 1 / 7
{/* Main Card */}
🔴

Phase 1: Redis 快取設定

設定 Session 快取伺服器

{alreadyConfigured && (

已載入先前儲存的配置 - 您可以查看或修改下方設定

)}

說明:Redis 用於儲存使用者 Session 資訊。NextAuth 會將登入狀態存放在 Redis 中。

{/* Form */}
setConfig({ ...config, host: e.target.value })} className="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg text-gray-100 placeholder-gray-400 focus:ring-2 focus:ring-red-500 focus:border-transparent" placeholder="例如: 10.1.0.20" />
setConfig({ ...config, port: parseInt(e.target.value) || 6379 })} className="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg text-gray-100 placeholder-gray-400 focus:ring-2 focus:ring-red-500 focus:border-transparent" />
setConfig({ ...config, db: parseInt(e.target.value) || 0 })} className="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg text-gray-100 placeholder-gray-400 focus:ring-2 focus:ring-red-500 focus:border-transparent" />
setConfig({ ...config, password: e.target.value })} className="w-full px-4 py-2 bg-gray-700 border border-gray-600 rounded-lg text-gray-100 placeholder-gray-400 focus:ring-2 focus:ring-red-500 focus:border-transparent" placeholder="留空表示無密碼" />
{/* Test Result */} {testResult && (
{testResult.success ? '✅' : '❌'}

{testResult.success ? '連接成功' : '連接失敗'}

{testResult.message}

{testResult.success && testResult.redis_version && (

Redis 版本: {testResult.redis_version}

{testResult.memory_usage &&

記憶體使用: {testResult.memory_usage}

}
)}
)} {/* Action Buttons */}
) }