feat: LokiDeploy 初始提交 - 轻量级 K8s Loki 部署平台
Go(Gin) + React(Vite + shadcn/ui + Tailwind) 前后端分离,全中文 UI - 集群管理:Kubeconfig / Token 双接入,kubectl + helm 部署 - 主机管理:SSH 密钥 / 密码双认证,CPU/内存/磁盘使用率监控,SSH 错误中文友好提示 - 存储配置、部署管理、系统设置 - Docker 镜像内置 kubectl + helm,开箱即用 - run.sh 一键启停(start/stop/restart/status) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
2a93de600d
134 files changed
+19595
No files matched your search
@@ -0,0 +1,131 @@
|
||||
import { useState } from 'react'
|
||||
import { KeyRound, Settings as SettingsIcon } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { authApi } from '@/srv/api'
|
||||
|
||||
export default function Settings() {
|
||||
const [oldPassword, setOldPassword] = useState('')
|
||||
const [newPassword, setNewPassword] = useState('')
|
||||
const [confirmPassword, setConfirmPassword] = useState('')
|
||||
const [changing, setChanging] = useState(false)
|
||||
|
||||
const handleChangePassword = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (newPassword !== confirmPassword) {
|
||||
alert('两次输入的密码不一致')
|
||||
return
|
||||
}
|
||||
setChanging(true)
|
||||
try {
|
||||
await authApi.changePassword(oldPassword, newPassword)
|
||||
alert('密码修改成功')
|
||||
setOldPassword('')
|
||||
setNewPassword('')
|
||||
setConfirmPassword('')
|
||||
} catch (err: unknown) {
|
||||
const message = err instanceof Error ? err.message : '密码修改失败'
|
||||
alert(message)
|
||||
} finally {
|
||||
setChanging(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold text-slate-800 dark:text-white">系统设置</h2>
|
||||
<p className="text-sm text-slate-500">修改登录密码与查看系统信息</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
{/* 修改密码 */}
|
||||
<Card className="border-slate-200 dark:border-slate-800">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-base flex items-center gap-2">
|
||||
<KeyRound className="w-4 h-4" />
|
||||
修改密码
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleChangePassword} className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="old-pwd">当前密码</Label>
|
||||
<Input
|
||||
id="old-pwd"
|
||||
type="password"
|
||||
value={oldPassword}
|
||||
onChange={(e) => setOldPassword(e.target.value)}
|
||||
placeholder="请输入当前密码"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="new-pwd">新密码</Label>
|
||||
<Input
|
||||
id="new-pwd"
|
||||
type="password"
|
||||
value={newPassword}
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
placeholder="请输入新密码(至少 6 位)"
|
||||
required
|
||||
minLength={6}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="confirm-pwd">确认新密码</Label>
|
||||
<Input
|
||||
id="confirm-pwd"
|
||||
type="password"
|
||||
value={confirmPassword}
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
placeholder="请再次输入新密码"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" className="bg-emerald-600 hover:bg-emerald-700" disabled={changing}>
|
||||
{changing ? '修改中...' : '修改密码'}
|
||||
</Button>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 关于 */}
|
||||
<Card className="border-slate-200 dark:border-slate-800">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-base flex items-center gap-2">
|
||||
<SettingsIcon className="w-4 h-4" />
|
||||
关于 LokiDeploy
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between py-2 border-b border-slate-100 dark:border-slate-800">
|
||||
<span className="text-sm text-slate-500">版本</span>
|
||||
<span className="text-sm font-medium">v1.0.0</span>
|
||||
</div>
|
||||
<div className="flex justify-between py-2 border-b border-slate-100 dark:border-slate-800">
|
||||
<span className="text-sm text-slate-500">后端</span>
|
||||
<span className="text-sm font-medium">Go + Gin + JSON 文件存储</span>
|
||||
</div>
|
||||
<div className="flex justify-between py-2 border-b border-slate-100 dark:border-slate-800">
|
||||
<span className="text-sm text-slate-500">前端</span>
|
||||
<span className="text-sm font-medium">React + TypeScript + Tailwind CSS</span>
|
||||
</div>
|
||||
<div className="flex justify-between py-2 border-b border-slate-100 dark:border-slate-800">
|
||||
<span className="text-sm text-slate-500">部署工具</span>
|
||||
<span className="text-sm font-medium">kubectl + helm(镜像内置)</span>
|
||||
</div>
|
||||
<div className="flex justify-between py-2">
|
||||
<span className="text-sm text-slate-500">简介</span>
|
||||
<span className="text-sm font-medium text-right">轻量级 K8s Loki 部署平台</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user