小程序后端增强绑定能力并支持多设备列表
This commit is contained in:
@@ -252,6 +252,40 @@ class BindingDAO(BaseDAO):
|
||||
.first()
|
||||
)
|
||||
|
||||
def list_by_user(self, user_id: int, limit: int = 20, cursor: int = None) -> list[Mapping]:
|
||||
params = {"user_id": user_id, "limit": limit + 1}
|
||||
where = "db.owner_user_id = :user_id AND db.status = 1"
|
||||
if cursor is not None:
|
||||
where += " AND db.id < :cursor"
|
||||
params["cursor"] = cursor
|
||||
|
||||
rows = (
|
||||
self.db.execute(
|
||||
text(
|
||||
f"""
|
||||
SELECT
|
||||
db.id,
|
||||
db.device_id,
|
||||
db.child_id,
|
||||
c.child_name,
|
||||
db.status,
|
||||
db.bound_at
|
||||
FROM device_bindings AS db
|
||||
LEFT JOIN children AS c
|
||||
ON c.child_id = db.child_id
|
||||
AND c.status = 1
|
||||
WHERE {where}
|
||||
ORDER BY db.id DESC
|
||||
LIMIT :limit
|
||||
"""
|
||||
),
|
||||
params,
|
||||
)
|
||||
.mappings()
|
||||
.all()
|
||||
)
|
||||
return rows
|
||||
|
||||
def get_by_device(self, device_id: str, user_id: int) -> Optional[Mapping]:
|
||||
return (
|
||||
self.db.execute(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
|
||||
from pydantic import BaseModel
|
||||
|
||||
try:
|
||||
@@ -45,6 +45,20 @@ class BindingGetResponse(BaseModel):
|
||||
bound_at: datetime
|
||||
|
||||
|
||||
class BindingListItem(BaseModel):
|
||||
device_id: str
|
||||
child_id: int | None
|
||||
child_name: str | None = None
|
||||
status: int
|
||||
bound_at: datetime
|
||||
|
||||
|
||||
class BindingListResponse(BaseModel):
|
||||
items: list[BindingListItem]
|
||||
total: int
|
||||
next_cursor: int | None = None
|
||||
|
||||
|
||||
class BindHistoryItem(BaseModel):
|
||||
device_id: str
|
||||
child_id: int | None
|
||||
@@ -140,6 +154,30 @@ def get_current_binding(
|
||||
return binding
|
||||
|
||||
|
||||
@router.get("", response_model=BindingListResponse)
|
||||
def list_bindings(
|
||||
request: Request,
|
||||
cursor: int | None = Query(default=None, ge=1),
|
||||
limit: int = Query(default=20, ge=1, le=100),
|
||||
current_user_id: int = Depends(get_current_user_id),
|
||||
db=Depends(get_db_session),
|
||||
) -> BindingListResponse:
|
||||
service = BindingService(db)
|
||||
rows, has_more = service.list_bindings(current_user_id, limit, cursor)
|
||||
next_cursor = int(rows[-1]["id"]) if has_more and rows else None
|
||||
items = [
|
||||
BindingListItem(
|
||||
device_id=row["device_id"],
|
||||
child_id=row["child_id"],
|
||||
child_name=row["child_name"],
|
||||
status=row["status"],
|
||||
bound_at=row["bound_at"],
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
return BindingListResponse(items=items, total=len(items), next_cursor=next_cursor)
|
||||
|
||||
|
||||
@router.get("/{device_id}", response_model=BindingGetResponse)
|
||||
def get_binding(
|
||||
device_id: str,
|
||||
|
||||
@@ -31,6 +31,12 @@ class BindingService:
|
||||
def get_current_binding(self, user_id: int) -> Optional[Mapping]:
|
||||
return self.dao.get_current_by_user(user_id)
|
||||
|
||||
def list_bindings(self, user_id: int, limit: int = 20, cursor: int = None) -> tuple[list, bool]:
|
||||
rows = self.dao.list_by_user(user_id, limit, cursor)
|
||||
has_more = len(rows) > limit
|
||||
rows = rows[:limit]
|
||||
return rows, has_more
|
||||
|
||||
def direct_bind(self, device_id: str, child_id: int | None, user_id: int) -> Mapping:
|
||||
self.dao.direct_bind(device_id, child_id, user_id)
|
||||
return {"device_id": device_id, "child_id": child_id}
|
||||
|
||||
Reference in New Issue
Block a user