From 8f4e0a2411ee034068bd207a1d33394af66168fb Mon Sep 17 00:00:00 2001 From: Jeason <1710884619@qq.com> Date: Wed, 18 Mar 2026 09:45:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E5=90=8E=E7=AB=AF=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=B5=81=E5=AF=B9=E9=BD=90=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端改动: GET /api/v1/accounts 现在返回分页格式 {items, total, page, size, total_pages, status_counts},默认每页 12 个 批量操作用 size=500 一次拉全部 前端改动: base.html — 加了移动端汉堡菜单、全局响应式样式、pagination disabled 状态 dashboard.html — 账号卡片分页,统计数据从 API 的 status_counts 取,移动端单列布局 account_detail.html — 签到记录改成上下两行布局(topic+状态 / 消息+时间),分页用统一的上一页/下一页样式,移动端适配 分页逻辑统一:前后端都用 page/total_pages 字段,pagination 组件显示当前页 ±2 页码。 --- backend/api_service/app/routers/accounts.py | 38 ++- backend/task_scheduler/app/__init__.py | 1 + backend/task_scheduler/app/tasks/__init__.py | 1 + frontend/app.py | 28 +- frontend/templates/account_detail.html | 126 ++++---- frontend/templates/base.html | 229 +++++--------- frontend/templates/dashboard.html | 302 +++++++------------ 7 files changed, 309 insertions(+), 416 deletions(-) create mode 100644 backend/task_scheduler/app/__init__.py create mode 100644 backend/task_scheduler/app/tasks/__init__.py diff --git a/backend/api_service/app/routers/accounts.py b/backend/api_service/app/routers/accounts.py index 2608404..df0b9be 100644 --- a/backend/api_service/app/routers/accounts.py +++ b/backend/api_service/app/routers/accounts.py @@ -92,15 +92,49 @@ async def create_account( @router.get("") async def list_accounts( + page: int = 1, + size: int = 12, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): + from sqlalchemy import func as sa_func + + # Total count + count_q = select(sa_func.count()).select_from( + select(Account).where(Account.user_id == user.id).subquery() + ) + total = (await db.execute(count_q)).scalar() or 0 + + # Status counts (for dashboard stats) + status_q = ( + select(Account.status, sa_func.count()) + .where(Account.user_id == user.id) + .group_by(Account.status) + ) + status_rows = (await db.execute(status_q)).all() + status_counts = {row[0]: row[1] for row in status_rows} + + # Paginated list + offset = (max(1, page) - 1) * size result = await db.execute( - select(Account).where(Account.user_id == user.id) + select(Account) + .where(Account.user_id == user.id) + .order_by(Account.created_at.desc()) + .offset(offset) + .limit(size) ) accounts = result.scalars().all() + total_pages = (total + size - 1) // size if total > 0 else 0 + return success_response( - [_account_to_dict(a) for a in accounts], + { + "items": [_account_to_dict(a) for a in accounts], + "total": total, + "page": page, + "size": size, + "total_pages": total_pages, + "status_counts": status_counts, + }, "Accounts retrieved", ) diff --git a/backend/task_scheduler/app/__init__.py b/backend/task_scheduler/app/__init__.py new file mode 100644 index 0000000..04e3b66 --- /dev/null +++ b/backend/task_scheduler/app/__init__.py @@ -0,0 +1 @@ +# Task scheduler app diff --git a/backend/task_scheduler/app/tasks/__init__.py b/backend/task_scheduler/app/tasks/__init__.py new file mode 100644 index 0000000..322ce79 --- /dev/null +++ b/backend/task_scheduler/app/tasks/__init__.py @@ -0,0 +1 @@ +# Task modules diff --git a/frontend/app.py b/frontend/app.py index a690be5..8733131 100644 --- a/frontend/app.py +++ b/frontend/app.py @@ -213,18 +213,32 @@ def logout(): @app.route('/dashboard') @login_required def dashboard(): + page = request.args.get('page', 1, type=int) try: response = api_request( 'GET', f'{API_BASE_URL}/api/v1/accounts', + params={'page': page, 'size': 12}, ) data = response.json() - accounts = data.get('data', []) if data.get('success') else [] + if data.get('success'): + payload = data.get('data', {}) + # 兼容旧版 API(返回列表)和新版(返回分页对象) + if isinstance(payload, list): + accounts = payload + pagination = {'items': payload, 'total': len(payload), 'page': 1, 'size': len(payload), 'total_pages': 1, 'status_counts': {}} + else: + accounts = payload.get('items', []) + pagination = payload + else: + accounts = [] + pagination = {'items': [], 'total': 0, 'page': 1, 'size': 12, 'total_pages': 0, 'status_counts': {}} except requests.RequestException: accounts = [] + pagination = {'items': [], 'total': 0, 'page': 1, 'size': 12, 'total_pages': 0, 'status_counts': {}} flash('加载账号列表失败', 'warning') - return render_template('dashboard.html', accounts=accounts, user=session.get('user')) + return render_template('dashboard.html', accounts=accounts, pagination=pagination, user=session.get('user')) @app.route('/accounts/new') @login_required @@ -841,9 +855,10 @@ def delete_task(task_id): def batch_verify(): """批量验证所有账号的 Cookie 有效性""" try: - response = api_request('GET', f'{API_BASE_URL}/api/v1/accounts') + response = api_request('GET', f'{API_BASE_URL}/api/v1/accounts', params={'page': 1, 'size': 500}) data = response.json() - accounts = data.get('data', []) if data.get('success') else [] + payload = data.get('data', {}) if data.get('success') else {} + accounts = payload.get('items', []) if isinstance(payload, dict) else payload valid = invalid = errors = 0 for account in accounts: @@ -871,9 +886,10 @@ def batch_verify(): def batch_signin(): """批量签到所有正常状态的账号""" try: - response = api_request('GET', f'{API_BASE_URL}/api/v1/accounts') + response = api_request('GET', f'{API_BASE_URL}/api/v1/accounts', params={'page': 1, 'size': 500}) data = response.json() - accounts = data.get('data', []) if data.get('success') else [] + payload = data.get('data', {}) if data.get('success') else {} + accounts = payload.get('items', []) if isinstance(payload, dict) else payload total_signed = total_already = total_failed = 0 processed = 0 diff --git a/frontend/templates/account_detail.html b/frontend/templates/account_detail.html index fb9c4f0..5229bd6 100644 --- a/frontend/templates/account_detail.html +++ b/frontend/templates/account_detail.html @@ -4,44 +4,41 @@ {% block extra_css %} {% endblock %} @@ -50,9 +47,9 @@
暂无定时任务
+暂无定时任务
{% endif %}暂无签到记录
+暂无签到记录
{% endif %}