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
@@ -31,8 +31,12 @@ type ResourceType =
|
||||
|
||||
// 支持可视化编辑/新建的资源类型 // Logan.Li
|
||||
const VISUAL_RESOURCE_TYPES: ResourceType[] = ['services', 'ingresses', 'configmaps', 'secrets', 'pvcs'];
|
||||
/** Deployment 列表:新建 + YAML 导入,不做批量导出 // Logan.Li */
|
||||
const DEPLOYMENT_LIST_TYPES: ResourceType[] = ['deployments'];
|
||||
/** 支持命名空间 YAML 批量导出(对齐集群导出)// Logan.Li */
|
||||
const EXPORT_YAML_TYPES: ResourceType[] = ['deployments', 'services', 'ingresses', 'configmaps', 'secrets'];
|
||||
const EXPORT_YAML_TYPES: ResourceType[] = ['services', 'ingresses', 'configmaps', 'secrets'];
|
||||
/** 列表页保留 CSV/JSON 导出的配置类资源 // Logan.Li */
|
||||
const BULK_EXPORT_TYPES: ResourceType[] = ['services', 'ingresses', 'configmaps', 'secrets', 'pvcs'];
|
||||
|
||||
const VisualActions = ({ name, opts }: { name: string; opts: { onYaml?: (n: string) => void; onEdit?: (n: string) => void } }) => (
|
||||
<div className="flex items-center gap-0.5">
|
||||
@@ -52,7 +56,7 @@ const RESOURCE_CONFIG: Record<ResourceType, {
|
||||
}> = {
|
||||
deployments: {
|
||||
title: 'Deployments', subtitle: 'Deployment 工作负载运行状态', icon: Boxes,
|
||||
columns: ['名称', '命名空间', '副本', '镜像', '操作'],
|
||||
columns: ['名称', '命名空间', '副本', '镜像'],
|
||||
renderRow: (d, opts) => (
|
||||
<TableRow key={d.name} className="border-slate-800 hover:bg-slate-800/30 cursor-pointer" onClick={() => opts.onDetail?.(d)}>
|
||||
<TableCell className="font-medium text-slate-200">{d.name}</TableCell>
|
||||
@@ -72,10 +76,6 @@ const RESOURCE_CONFIG: Record<ResourceType, {
|
||||
})()}
|
||||
</TableCell>
|
||||
<TableCell className="text-xs text-slate-500 max-w-[200px] truncate">{d.image || '-'}</TableCell>
|
||||
<TableCell onClick={(e) => e.stopPropagation()}>
|
||||
<Button variant="ghost" size="sm" className="h-7 px-2 text-xs text-blue-400 hover:text-blue-300 hover:bg-blue-500/10" title="查看 YAML"
|
||||
onClick={() => opts.onYaml?.(d.name)}><FileCode className="h-3.5 w-3.5 mr-1" />YAML</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
),
|
||||
},
|
||||
@@ -95,13 +95,13 @@ const RESOURCE_CONFIG: Record<ResourceType, {
|
||||
<TableCell className={(p.restart_count > 0 ? 'text-yellow-400' : 'text-slate-500')}>{p.restart_count || 0}</TableCell>
|
||||
<TableCell className="text-xs text-slate-500 max-w-[200px] truncate">{p.image || '-'}</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-1">
|
||||
<Button variant="ghost" size="sm" className="h-7 px-2 text-xs text-emerald-400 hover:text-emerald-300 hover:bg-emerald-500/10" title="终端"
|
||||
onClick={() => (opts as Record<string, any>).onTerminal?.(p)}><Terminal className="h-3.5 w-3.5 mr-1" />终端</Button>
|
||||
<Button variant="ghost" size="sm" className="h-7 px-2 text-xs text-amber-400 hover:text-amber-300 hover:bg-amber-500/10" title="文件浏览器"
|
||||
onClick={() => (opts as Record<string, any>).onFileBrowser?.(p)}><HardDrive className="h-3.5 w-3.5 mr-1" />文件浏览器</Button>
|
||||
<Button variant="ghost" size="sm" className="h-7 px-2 text-xs text-blue-400 hover:text-blue-300 hover:bg-blue-500/10" title="查看YAML"
|
||||
onClick={() => opts.onYaml?.(p.name)}><FileCode className="h-3.5 w-3.5 mr-1" />YAML</Button>
|
||||
<div className="flex items-center gap-0.5">
|
||||
<Button variant="ghost" size="sm" className="h-7 w-7 p-0 shrink-0 text-emerald-400" title="终端"
|
||||
onClick={() => (opts as Record<string, any>).onTerminal?.(p)}><Terminal className="h-3.5 w-3.5" /></Button>
|
||||
<Button variant="ghost" size="sm" className="h-7 w-7 p-0 shrink-0 text-amber-400" title="文件"
|
||||
onClick={() => (opts as Record<string, any>).onFileBrowser?.(p)}><HardDrive className="h-3.5 w-3.5" /></Button>
|
||||
<Button variant="ghost" size="sm" className="h-7 w-7 p-0 shrink-0 text-blue-400" title="YAML"
|
||||
onClick={() => opts.onYaml?.(p.name)}><FileCode className="h-3.5 w-3.5" /></Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -414,7 +414,13 @@ export default function NamespaceResourcePage() {
|
||||
setYamlItem({ resource: type, name, editMode: true });
|
||||
}
|
||||
};
|
||||
const handleCreate = () => setVisualItem({ resource: type, name: '', isCreate: true });
|
||||
const handleCreate = () => {
|
||||
if (type === 'deployments') {
|
||||
navigate(`/kubernetes/${clusterCode}/namespace/${namespace}/workload/edit/Deployment/_create`);
|
||||
return;
|
||||
}
|
||||
setVisualItem({ resource: type, name: '', isCreate: true });
|
||||
};
|
||||
const handleExportCSV = () => kubernetesApi.exportAsCSV(`${type}-${clusterCode}-${namespace}.csv`, filtered);
|
||||
const handleExportJSON = () => kubernetesApi.exportAsJSON(`${type}-${clusterCode}-${namespace}.json`, filtered);
|
||||
const handleExportYaml = async () => {
|
||||
@@ -484,18 +490,22 @@ export default function NamespaceResourcePage() {
|
||||
<Button variant="outline" size="icon" className="h-9 w-9 border-slate-700 text-slate-400" onClick={loadData} disabled={loading}>
|
||||
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" className="h-9 border-slate-700 text-slate-400 text-xs" onClick={handleExportCSV} title="导出CSV">
|
||||
<Download className="h-3 w-3 mr-1" />CSV
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" className="h-9 border-slate-700 text-slate-400 text-xs" onClick={handleExportJSON} title="导出JSON">
|
||||
<Download className="h-3 w-3 mr-1" />JSON
|
||||
</Button>
|
||||
{BULK_EXPORT_TYPES.includes(type) && (
|
||||
<>
|
||||
<Button variant="outline" size="sm" className="h-9 border-slate-700 text-slate-400 text-xs" onClick={handleExportCSV} title="导出CSV">
|
||||
<Download className="h-3 w-3 mr-1" />CSV
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" className="h-9 border-slate-700 text-slate-400 text-xs" onClick={handleExportJSON} title="导出JSON">
|
||||
<Download className="h-3 w-3 mr-1" />JSON
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{EXPORT_YAML_TYPES.includes(type) && (
|
||||
<Button variant="outline" size="sm" className="h-9 border-slate-700 text-slate-400 text-xs" onClick={handleExportYaml} title="导出命名空间 YAML(tar.gz)">
|
||||
<Download className="h-3 w-3 mr-1" />导出YAML
|
||||
</Button>
|
||||
)}
|
||||
{VISUAL_RESOURCE_TYPES.includes(type) && (
|
||||
{(VISUAL_RESOURCE_TYPES.includes(type) || DEPLOYMENT_LIST_TYPES.includes(type)) && (
|
||||
<>
|
||||
<Button variant="outline" size="sm" className="h-9 border-slate-700 text-slate-400 text-xs" onClick={() => setShowYamlImport(true)}>
|
||||
<Upload className="h-3 w-3 mr-1" />导入
|
||||
|
||||
Reference in new issue
Block a user