/** * Admin 后台 - 系统配置管理页面(报刊风) * * 功能: * - 登录与鉴权说明(ADMIN_PASSWORD,HttpOnly 会话 Cookie) * - 显示当前 .env 配置(脱敏;后端暂无配置端点,为静态说明) * - 配置修改指南 */ import { useEffect, useState, useCallback } from 'react' import { fetchSystemConfig } from '../dal' import { changePassword, fetchAuthState, UNAUTHORIZED_EVENT } from '../api' import { Card, CardBody, CardHeader, Badge, SectionHeader, Alert, Spinner, SkeletonBlock } from '../components' export default function ConfigPage() { const [config, setConfig] = useState([]) const [loading, setLoading] = useState(true) const [passwordOrigin, setPasswordOrigin] = useState<'db' | 'env' | 'none' | null>(null) // 修改密码表单 const [currentPwd, setCurrentPwd] = useState('') const [newPwd, setNewPwd] = useState('') const [confirmPwd, setConfirmPwd] = useState('') const [pwdBusy, setPwdBusy] = useState(false) const [pwdNotice, setPwdNotice] = useState<{ ok: boolean; text: string } | null>(null) const loadConfig = useCallback(async () => { setLoading(true) try { const data = await fetchSystemConfig() setConfig(data) } catch { setConfig([]) } finally { setLoading(false) } }, []) useEffect(() => { loadConfig() fetchAuthState() .then(s => setPasswordOrigin(s.password_origin ?? null)) .catch(() => setPasswordOrigin(null)) }, [loadConfig]) async function handleChangePassword(e: React.FormEvent) { e.preventDefault() setPwdNotice(null) if (newPwd !== confirmPwd) { setPwdNotice({ ok: false, text: '两次输入的新密码不一致' }) return } setPwdBusy(true) try { const res = await changePassword(currentPwd, newPwd) setPwdNotice({ ok: true, text: res.message }) // 密码即会话密钥,修改后所有会话失效:主动切回登录页 setTimeout(() => window.dispatchEvent(new CustomEvent(UNAUTHORIZED_EVENT)), 1500) } catch (err) { setPwdNotice({ ok: false, text: err instanceof Error ? err.message.split('\n')[0] : '修改失败' }) } finally { setPwdBusy(false) } } return (
{/* 登录与鉴权 */}

密码初始来自服务器 .env 的{' '} ADMIN_PASSWORD(启动时自动转为哈希),在下方修改后以{' '} scrypt 哈希安全存入数据库并立即生效,明文不再留存。 密码即会话签名密钥,修改后所有已登录会话失效,需用新密码重新登录。 脚本直连接口可改用 ADMIN_API_KEY(请求头 X-API-Key)。

{passwordOrigin && (

当前密码来源: {passwordOrigin === 'db' ? ( 数据库(scrypt 哈希) ) : passwordOrigin === 'env' ? ( .env 初始值 ) : ( 未配置 )}

)} {/* 修改密码表单 */}
setCurrentPwd(e.target.value)} autoComplete="current-password" className="field w-full" />
setNewPwd(e.target.value)} autoComplete="new-password" className="field w-full" />
setConfirmPwd(e.target.value)} autoComplete="new-password" className="field w-full" />
{pwdNotice && ( )}

修改成功后会自动退出登录,请用新密码重新登录。

{/* 快速导航 */}
数据源配置
管理采集源 API Key
LLM 配置
管理模型连接与统计
{/* 配置列表 */} {loading ? (<> 加载中) : '刷新'} } /> {loading ? (
{[1, 2, 3, 4, 5].map(i => ( ))}
) : config.length > 0 ? (
{config.map(item => (
{item.key} {item.is_sensitive && 敏感}
{item.value_masked}
{item.description}
))}
) : (

无法加载配置信息

)}
{/* 修改指南 */}

通过 SSH 修改 .env

{`# 连接到部署主机
ssh user@your-server-ip

# 进入项目目录
cd /vol2/1000/Docker/Profeto

# 编辑 .env 文件
nano .env

# 修改后重启后端服务
docker compose restart api

# 查看日志确认生效
docker compose logs -f api`}
            

常用配置项说明

{[ ['LLM_API_KEY', 'LLM 服务商的 API 密钥,用于调用大模型'], ['LLM_MODEL', '使用的模型名称,如 gpt-4o、claude-3-5-sonnet'], ['LLM_BASE_URL', 'API 基础地址,支持兼容 OpenAI 协议的服务商'], ['ADMIN_PASSWORD', '管理后台登录密码,修改后重启 api 容器生效'], ['ADMIN_API_KEY', '脚本直连接口的鉴权密钥(请求头 X-API-Key)'], ['BZZOIRO_KEY', 'Bzzoiro 数据源 API 密钥'], ['DATABASE_URL', 'PostgreSQL 数据库连接字符串'], ].map(([key, desc]) => (
{key} {desc}
))}
) }