From fb78863ee69b1a39585a3b90c91b37ce668cbdc7 Mon Sep 17 00:00:00 2001 From: stu2not Date: Thu, 16 Apr 2026 18:20:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E7=BB=91=E5=AE=9A=E8=83=BD=E5=8A=9B=E5=B9=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mini-program/app/dao/binding.py | 34 +++++++++++++++++++++++ mini-program/app/routers/bindings.py | 40 +++++++++++++++++++++++++++- mini-program/app/service/binding.py | 6 +++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/mini-program/app/dao/binding.py b/mini-program/app/dao/binding.py index 87bfa00..8d8a39d 100644 --- a/mini-program/app/dao/binding.py +++ b/mini-program/app/dao/binding.py @@ -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( diff --git a/mini-program/app/routers/bindings.py b/mini-program/app/routers/bindings.py index 8fffd5a..7bf2115 100644 --- a/mini-program/app/routers/bindings.py +++ b/mini-program/app/routers/bindings.py @@ -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, diff --git a/mini-program/app/service/binding.py b/mini-program/app/service/binding.py index abe1611..da01612 100644 --- a/mini-program/app/service/binding.py +++ b/mini-program/app/service/binding.py @@ -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}