feat: 新增日志中心、功能优化与代码重构
- 新增 log_datasource.go / log_proxy.go / user_api_token.go 后端控制器 - 新增 log_datasource.go model - 新增 monitor/log-center.ts API 模块 - 新增 LogCenter 前端组件及页面 - 重构 deployment 相关组件 (HPDA/UpdateImageModal/bundle-yaml 等) - 新增 ResetPasswordDialog / code-snippet-block / copy-button 等 UI 组件 - 重构多个 k8s 相关组件 (TopologyView/ResourceVisualEditor/PodFileBrowser 等) - 更新多个 API 和工具函数 (auth.ts/monitor/index.ts/request.ts 等) - 更新静态资源 (index.html + 新 JS/CSS bundle) - 删除废弃静态资源文件
This commit is contained in:
1 parent
5ca0e6d83a
commit
8d46e8f352
197 files changed
+5014
-815
No files matched your search
@@ -0,0 +1,95 @@
|
||||
// 管理员重置用户密码弹窗 // Logan.Li
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import {
|
||||
Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Key, Loader2 } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { userApi } from '@/api';
|
||||
|
||||
interface ResetPasswordDialogProps {
|
||||
user: { id: number | string; username?: string; nickname?: string; authSource?: string } | null;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function ResetPasswordDialog({ user, onClose }: ResetPasswordDialogProps) {
|
||||
const { toast } = useToast();
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirm, setConfirm] = useState('');
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const isLdap = user?.authSource === 'ldap';
|
||||
const canSubmit = password.length >= 6 && password === confirm && !isLdap;
|
||||
|
||||
const handleReset = async () => {
|
||||
if (!user || !canSubmit) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
await userApi.resetUserPassword(user.id, password);
|
||||
toast({ title: '密码已重置', description: `用户 ${user.nickname || user.username} 的新密码已生效` });
|
||||
setPassword('');
|
||||
setConfirm('');
|
||||
onClose();
|
||||
} catch (e: any) {
|
||||
toast({ title: '重置失败', description: e?.message || String(e), variant: 'destructive' });
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={!!user} onOpenChange={(open) => { if (!open) { setPassword(''); setConfirm(''); onClose(); } }}>
|
||||
<DialogContent className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)] sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-[var(--dg-text-primary)] flex items-center gap-2">
|
||||
<Key className="h-5 w-5 text-[var(--dg-blue)]" />
|
||||
重置密码
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-[var(--dg-text-muted)]">
|
||||
{user ? `为「${user.nickname || user.username}」设置新密码` : ''}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{isLdap ? (
|
||||
<p className="text-sm text-amber-400/90 py-2">LDAP 用户请在 LDAP 目录中管理密码,不支持本地重置。</p>
|
||||
) : (
|
||||
<div className="space-y-3 py-1">
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-muted)]">新密码</Label>
|
||||
<Input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
placeholder="至少 6 位"
|
||||
className="mt-1 h-9 bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label className="text-xs text-[var(--dg-text-muted)]">确认密码</Label>
|
||||
<Input
|
||||
type="password"
|
||||
value={confirm}
|
||||
onChange={e => setConfirm(e.target.value)}
|
||||
placeholder="再次输入新密码"
|
||||
className="mt-1 h-9 bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="outline" className="border-[var(--dg-border)]" onClick={onClose}>取消</Button>
|
||||
{!isLdap && (
|
||||
<Button onClick={handleReset} disabled={!canSubmit || saving} className="bg-[var(--dg-blue)] hover:opacity-90">
|
||||
{saving ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : null}
|
||||
确认重置
|
||||
</Button>
|
||||
)}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import type { Role } from '@/types';
|
||||
import { SystemUserTab } from './SystemUserTab';
|
||||
import { SystemRolesTab } from './SystemRolesTab';
|
||||
import { SystemSettingsTab } from './SystemSettingsTab';
|
||||
import { ResetPasswordDialog } from './ResetPasswordDialog';
|
||||
import { useLdapManagement } from './useLdapManagement';
|
||||
import type { UserFormData } from './UserFormDialog';
|
||||
|
||||
@@ -56,6 +57,7 @@ export function SystemManager() {
|
||||
const [users, setUsers] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedUser, setSelectedUser] = useState<any | null>(null);
|
||||
const [resetPasswordUser, setResetPasswordUser] = useState<any | null>(null);
|
||||
const [selectedRole, setSelectedRole] = useState<Role | null>(null);
|
||||
|
||||
// 创建/编辑用户弹窗
|
||||
@@ -274,6 +276,7 @@ export function SystemManager() {
|
||||
openCreate={openCreate}
|
||||
openEdit={openEdit}
|
||||
handleDelete={handleDelete}
|
||||
onResetPassword={(u) => { setSelectedUser(null); setResetPasswordUser(u); }}
|
||||
importDialogOpen={importDialogOpen}
|
||||
setImportDialogOpen={setImportDialogOpen}
|
||||
importPreview={importPreview}
|
||||
@@ -307,6 +310,8 @@ export function SystemManager() {
|
||||
<SystemSettingsTab {...ldap.settingsTabProps} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
<ResetPasswordDialog user={resetPasswordUser} onClose={() => setResetPasswordUser(null)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -48,6 +48,7 @@ interface SystemUserTabProps {
|
||||
openCreate: () => void;
|
||||
openEdit: ( user: any) => void;
|
||||
handleDelete: ( user: any) => void;
|
||||
onResetPassword?: (user: any) => void;
|
||||
// CSV import
|
||||
importDialogOpen: 'csv' | 'ldap' | null;
|
||||
setImportDialogOpen: (v: 'csv' | 'ldap' | null) => void;
|
||||
@@ -89,6 +90,7 @@ export function SystemUserTab({
|
||||
openCreate,
|
||||
openEdit,
|
||||
handleDelete,
|
||||
onResetPassword,
|
||||
importDialogOpen,
|
||||
setImportDialogOpen,
|
||||
importPreview,
|
||||
@@ -277,6 +279,7 @@ export function SystemUserTab({
|
||||
setSelectedUser={setSelectedUser}
|
||||
getUserStatusBadge={getUserStatusBadge}
|
||||
openEdit={openEdit}
|
||||
onResetPassword={onResetPassword}
|
||||
/>
|
||||
|
||||
<UserFormDialog
|
||||
|
||||
@@ -16,6 +16,7 @@ interface UserDetailDialogProps {
|
||||
setSelectedUser: (u: any | null) => void;
|
||||
getUserStatusBadge: (status: 'active' | 'inactive') => React.ReactNode;
|
||||
openEdit: ( user: any) => void;
|
||||
onResetPassword?: (user: any) => void;
|
||||
}
|
||||
|
||||
// UserDetailDialog 仅展示选中用户的基本信息和角色列表 // Logan.Li
|
||||
@@ -24,6 +25,7 @@ export function UserDetailDialog({
|
||||
setSelectedUser,
|
||||
getUserStatusBadge,
|
||||
openEdit,
|
||||
onResetPassword,
|
||||
}: UserDetailDialogProps) {
|
||||
return (
|
||||
<Dialog open={!!selectedUser} onOpenChange={() => setSelectedUser(null)}>
|
||||
@@ -81,7 +83,12 @@ export function UserDetailDialog({
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="outline" className="border-slate-700 text-slate-300">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="border-slate-700 text-slate-300"
|
||||
disabled={selectedUser?.authSource === 'ldap'}
|
||||
onClick={() => selectedUser && onResetPassword?.(selectedUser)}
|
||||
>
|
||||
<Key className="h-4 w-4 mr-2" />
|
||||
重置密码
|
||||
</Button>
|
||||
|
||||
Reference in new issue
Block a user