- 4个数据源菜单(MySQL/PG/Redis/Mongo)合并为1个「数据源」 - InstancePage 改为统一入口,顶部Tab切换类型过滤 - 添加数据源改为弹框Modal(默认MySQL) - 去掉左下角用户区,退出登录移到右上角header - 侧边栏收窄220px,整体布局更紧凑 - 后端202 tests passing - 前端构建零错误
63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
"""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
|