refactor: 数据源菜单合一+布局优化

- 4个数据源菜单(MySQL/PG/Redis/Mongo)合并为1个「数据源」
- InstancePage 改为统一入口,顶部Tab切换类型过滤
- 添加数据源改为弹框Modal(默认MySQL)
- 去掉左下角用户区,退出登录移到右上角header
- 侧边栏收窄220px,整体布局更紧凑
- 后端202 tests passing
- 前端构建零错误
This commit is contained in:
logan committed 2026-05-22 22:53:48 +08:00
1 parent bab55d3927
commit 5cbd0e3441
23 files changed
+2881 -94

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
"""Backup management API."""
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.core.security import require_role
from app.models.user import User
from app.models.backup import Backup
from app.schemas.backup import BackupCreate, BackupResponse
router = APIRouter(prefix="/backups", tags=["备份管理"])
@router.get("", response_model=List[BackupResponse])
async def list_backups(
instance_id: Optional[int] = Query(None),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_role("admin", "dba")),
):
stmt = select(Backup).order_by(Backup.id.desc())
if instance_id:
stmt = stmt.where(Backup.instance_id == instance_id)
result = await db.execute(stmt)
backups = result.scalars().all()
return backups
@router.post("", response_model=BackupResponse, status_code=201)
async def create_backup(
data: BackupCreate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_role("admin", "dba")),
):
backup = Backup(
title=data.title,
instance_id=data.instance_id,
database=data.database,
filename=data.database + "_" + str(data.instance_id) + ".sql",
status="pending",
created_by=current_user.id,
remark=data.remark,
)
db.add(backup)
await db.commit()
await db.refresh(backup)
return backup
@router.get("/{backup_id}", response_model=BackupResponse)
async def get_backup(
backup_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_role("admin", "dba")),
):
result = await db.execute(select(Backup).where(Backup.id == backup_id))
backup = result.scalar_one_or_none()
if not backup:
raise HTTPException(status_code=404, detail="备份记录不存在")
return backup