feat: 工具配置增强、站点拨测与日志中心多项改进

- 工具配置:新增卸载 API/UI、Go 工具链、流水线构建自动安装依赖
- 修复 ListTools VerifyTool 递归栈溢出导致获取工具配置失败
- Node.js Alpine 安装改用 unofficial-builds musl 预编译包与 index.json 解析 LTS
- 站点拨测:详情页路由、告警自动恢复、并发拨测与默认可观测频率
- 日志中心:RBAC、查询构建器、ES/Loki 增强与审计 request/response 展示
- 发布配置:构建节点、流水线远程执行、Deploy RBAC 导航拆分
This commit is contained in:
Logan committed 2026-07-02 07:47:33 +08:00
1 parent cde7bbe540
commit 7e1c8f583c
84 files changed
+7729 -1507

No files matched your search

@@ -6,7 +6,9 @@ import { Badge } from '@/components/ui/badge';
import { PageShell } from '@/components/layout/PageShell';
import { ContentPanel } from '@/components/layout/ContentPanel';
import { PageEmpty } from '@/components/layout/PageEmpty';
import { StatStrip } from '@/components/ui/stat-strip';
import { useSearchParams } from 'react-router-dom';
import BuildNodesManager from './BuildNodesManager';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
@@ -98,8 +100,12 @@ function EnvFormDialog({ open, onClose, onSaved, editData }: { open: boolean; on
);
}
const CONFIG_TABS = ['repos', 'registries', 'environments', 'tools', 'build-nodes'] as const;
export default function DeployCredentials() {
const _confirm = useConfirm();
const [searchParams] = useSearchParams();
const tabFromUrl = searchParams.get('tab');
const [repos, setRepos] = useState<Repo[]>([]);
const [registries, setRegistries] = useState<Registry[]>([]);
const [environments, setEnvironments] = useState<Environment[]>([]);
@@ -109,7 +115,9 @@ export default function DeployCredentials() {
const [editingId, setEditingId] = useState<number | null>(null);
const [envDialogOpen, setEnvDialogOpen] = useState(false);
const [editEnv, setEditEnv] = useState<Environment | null>(null);
const [activeTab, setActiveTab] = useState('repos');
const [activeTab, setActiveTab] = useState(
tabFromUrl && (CONFIG_TABS as readonly string[]).includes(tabFromUrl) ? tabFromUrl : 'repos',
);
const fetchAll = async () => {
setLoading(true);
@@ -142,29 +150,21 @@ export default function DeployCredentials() {
{ id: 'repos', label: 'Git 仓库', badge: repos.length || undefined },
{ id: 'registries', label: '镜像仓库', badge: registries.length || undefined },
{ id: 'environments', label: '环境管理', badge: environments.length || undefined },
{ id: 'build-nodes', label: '构建节点' },
{ id: 'tools', label: '工具配置' },
];
return (
<PageShell
variant="list"
title="发布配置管理"
subtitle="Git 仓库、镜像仓库、环境与工具配置"
title="发布配置"
subtitle="Git 仓库、镜像仓库、环境与工具"
icon={<Settings2 className="h-5 w-5" />}
loading={loading}
tabs={pageTabs}
activeTab={activeTab}
onTabChange={setActiveTab}
metrics={(
<StatStrip
items={[
{ label: 'Git 仓库', value: repos.length, color: 'blue' },
{ label: '镜像仓库', value: registries.length, color: 'cyan' },
{ label: '环境', value: environments.length, color: 'purple' },
]}
/>
)}
actions={(
actions={activeTab === 'build-nodes' ? undefined : (
<>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={fetchAll}>
<RefreshCw className="w-4 h-4 mr-1" />刷新
@@ -177,6 +177,7 @@ export default function DeployCredentials() {
</Button>
</>
)}
contentClassName="space-y-4"
>
{activeTab === 'repos' && (
repos.length === 0 ? (
@@ -325,6 +326,8 @@ export default function DeployCredentials() {
</>
)}
{activeTab === 'build-nodes' && <BuildNodesManager embedded />}
{activeTab === 'tools' && <ToolConfigTab />}
<CredentialFormDialog