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

@@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button';
import { PageShell } from '@/components/layout/PageShell';
import { PageEmpty } from '@/components/layout/PageEmpty';
import { StatStrip } from '@/components/ui/stat-strip';
import { Input } from '@/components/ui/input';
import { Badge } from '@/components/ui/badge';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
@@ -21,7 +22,7 @@ interface GroupMember {
id: number; group_id: number; username: string; created_at: string;
}
export default function UserGroupsManager() {
export default function UserGroupsManager({ embedded = false }: { embedded?: boolean }) {
const _confirm = useConfirm();
const [groups, setGroups] = useState<Group[]>([]);
const [loading, setLoading] = useState(true);
@@ -83,33 +84,18 @@ export default function UserGroupsManager() {
const memberCount = groups.reduce((sum, g) => sum + (g.members || []).length, 0);
return (
<PageShell
variant="list"
title="用户组管理"
subtitle="创建用户组,将组授权给流水线,组内成员自动获得流水线权限"
icon={<Users className="h-5 w-5" />}
loading={loading}
metrics={(
<StatStrip
items={[
{ label: '用户组', value: groups.length, color: 'blue' },
{ label: '成员总数', value: memberCount, color: 'purple' },
]}
/>
)}
actions={(
<>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadGroups}>
<RefreshCw className="w-4 h-4 mr-1" />刷新
</Button>
<Button size="sm" className="dg-btn-primary" onClick={() => { setEditId(null); setFormName(''); setFormDesc(''); setFormOpen(true); }}>
<Plus className="w-4 h-4 mr-1" />新建用户组
</Button>
</>
)}
>
{!loading && groups.length === 0 ? (
const toolbar = embedded ? (
<div className="flex items-center justify-end gap-2 mb-3">
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadGroups}>
<RefreshCw className="w-4 h-4 mr-1" />刷新
</Button>
<Button size="sm" className="dg-btn-primary" onClick={() => { setEditId(null); setFormName(''); setFormDesc(''); setFormOpen(true); }}>
<Plus className="w-4 h-4 mr-1" />新建用户组
</Button>
</div>
) : null;
const listBody = !loading && groups.length === 0 ? (
<PageEmpty
icon={<Users className="h-10 w-10" />}
title="暂无用户组"
@@ -171,9 +157,9 @@ export default function UserGroupsManager() {
</div>
))}
</div>
)}
);
{/* Form Dialog */}
const formDialog = (
<Dialog open={formOpen} onOpenChange={setFormOpen}>
<DialogContent>
<DialogHeader><DialogTitle>{editId ? '编辑用户组' : '新建用户组'}</DialogTitle></DialogHeader>
@@ -187,6 +173,47 @@ export default function UserGroupsManager() {
</div>
</DialogContent>
</Dialog>
);
if (embedded) {
return (
<>
{toolbar}
{listBody}
{formDialog}
</>
);
}
return (
<PageShell
variant="list"
title="应用发布"
subtitle="用户组 — 批量授权流水线访问权限"
icon={<Users className="h-5 w-5" />}
loading={loading}
metrics={(
<StatStrip
items={[
{ label: '用户组', value: groups.length, color: 'blue' },
{ label: '成员总数', value: memberCount, color: 'purple' },
]}
/>
)}
actions={(
<>
<Button variant="outline" size="sm" className="dg-btn-secondary" onClick={loadGroups}>
<RefreshCw className="w-4 h-4 mr-1" />刷新
</Button>
<Button size="sm" className="dg-btn-primary" onClick={() => { setEditId(null); setFormName(''); setFormDesc(''); setFormOpen(true); }}>
<Plus className="w-4 h-4 mr-1" />新建用户组
</Button>
</>
)}
contentClassName="space-y-4"
>
{listBody}
{formDialog}
</PageShell>
);
}