feat: 告警/考勤/蓝牙/数据日志页面添加批量删除功能
- 新增 POST /api/alarms/batch-delete、/api/bluetooth/batch-delete、 /api/heartbeats/batch-delete 批量删除端点 (最多500条) - 四个页面表格添加全选复选框和"删除选中"按钮 - 提取通用 toggleAllCheckboxes/updateSelCount/_batchDelete 函数 - 数据日志页面根据当前查询类型自动路由到对应的批量删除API via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
@@ -131,6 +131,32 @@ async def alarm_stats(db: AsyncSession = Depends(get_db)):
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/batch-delete",
|
||||
response_model=APIResponse[dict],
|
||||
summary="批量删除告警记录 / Batch delete alarms",
|
||||
dependencies=[Depends(require_write)],
|
||||
)
|
||||
async def batch_delete_alarms(
|
||||
body: dict,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""批量删除告警记录,最多500条。 / Batch delete alarm records (max 500)."""
|
||||
alarm_ids = body.get("alarm_ids", [])
|
||||
if not alarm_ids:
|
||||
raise HTTPException(status_code=400, detail="alarm_ids is required")
|
||||
if len(alarm_ids) > 500:
|
||||
raise HTTPException(status_code=400, detail="Max 500 records per request")
|
||||
result = await db.execute(
|
||||
select(AlarmRecord).where(AlarmRecord.id.in_(alarm_ids))
|
||||
)
|
||||
records = list(result.scalars().all())
|
||||
for r in records:
|
||||
await db.delete(r)
|
||||
await db.flush()
|
||||
return APIResponse(data={"deleted": len(records)})
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{alarm_id}",
|
||||
response_model=APIResponse[AlarmRecordResponse],
|
||||
|
||||
@@ -142,6 +142,31 @@ async def device_bluetooth_records(
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/batch-delete",
|
||||
response_model=APIResponse[dict],
|
||||
summary="批量删除蓝牙记录 / Batch delete bluetooth records",
|
||||
)
|
||||
async def batch_delete_bluetooth(
|
||||
body: dict,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""批量删除蓝牙记录,最多500条。 / Batch delete bluetooth records (max 500)."""
|
||||
record_ids = body.get("record_ids", [])
|
||||
if not record_ids:
|
||||
raise HTTPException(status_code=400, detail="record_ids is required")
|
||||
if len(record_ids) > 500:
|
||||
raise HTTPException(status_code=400, detail="Max 500 records per request")
|
||||
result = await db.execute(
|
||||
select(BluetoothRecord).where(BluetoothRecord.id.in_(record_ids))
|
||||
)
|
||||
records = list(result.scalars().all())
|
||||
for r in records:
|
||||
await db.delete(r)
|
||||
await db.flush()
|
||||
return APIResponse(data={"deleted": len(records)})
|
||||
|
||||
|
||||
# NOTE: /{record_id} must be after /device/{device_id} to avoid route conflicts
|
||||
@router.get(
|
||||
"/{record_id}",
|
||||
|
||||
@@ -73,6 +73,31 @@ async def list_heartbeats(
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/batch-delete",
|
||||
response_model=APIResponse[dict],
|
||||
summary="批量删除心跳记录 / Batch delete heartbeats",
|
||||
)
|
||||
async def batch_delete_heartbeats(
|
||||
body: dict,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""批量删除心跳记录,最多500条。 / Batch delete heartbeat records (max 500)."""
|
||||
record_ids = body.get("record_ids", [])
|
||||
if not record_ids:
|
||||
raise HTTPException(status_code=400, detail="record_ids is required")
|
||||
if len(record_ids) > 500:
|
||||
raise HTTPException(status_code=400, detail="Max 500 records per request")
|
||||
result = await db.execute(
|
||||
select(HeartbeatRecord).where(HeartbeatRecord.id.in_(record_ids))
|
||||
)
|
||||
records = list(result.scalars().all())
|
||||
for r in records:
|
||||
await db.delete(r)
|
||||
await db.flush()
|
||||
return APIResponse(data={"deleted": len(records)})
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{heartbeat_id}",
|
||||
response_model=APIResponse[HeartbeatRecordResponse],
|
||||
|
||||
Reference in New Issue
Block a user