feat(dashboard): 最近动态改服务端分页

工作台「最近动态」原为聚合端点内嵌、固定截断前 20 条,操作日志变长后
既撑大响应又只能看到头部。改为独立分页端点:
- GET /api/v1/dashboard/activities,支持 pageNum/pageSize/module 筛选
- 模块筛选项与列表同源返回(全量模块名,不随翻页变化),前端不必再取一次全量
- 聚合端点去掉内嵌 activities,避免同一份数据两处查询

前端改用 usePagedList + 统一 AppPagination(每页 10/20/50),模块筛选由
本地过滤改为服务端筛选。集成测试 13 例(含翻页不重不漏 / 模块筛选 / 越权 403)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
liuwenxinandClaude Code committed 2026-10-23 16:15:09 +08:00
1 parent 32b7940067
commit 61fe5cca98
7 files changed
+835 -329

No files matched your search

+44 -3
View File
@@ -118,10 +118,20 @@ def _dashboard(client: TestClient, headers: dict, month: str | None = None) -> d
return resp.json()["data"]
def _activities(client: TestClient, headers: dict, **params) -> dict:
"""最近动态分页端点。"""
resp = client.get(f"{_DASHBOARD}/activities", params=params, headers=headers)
assert resp.status_code == 200, resp.text
return resp.json()["data"]
def test_权限_普通用户403文案(client: TestClient, normal: dict):
resp = client.get(_DASHBOARD, headers=normal["headers"])
assert resp.status_code == 403
assert resp.json()["message"] == "无权访问工作台"
# 最近动态分页端点同属工作台,权限一致
resp = client.get(f"{_DASHBOARD}/activities", headers=normal["headers"])
assert resp.status_code == 403
def test_总览_绩效合计与台账一致且非法月份400(client: TestClient, admin: dict):
@@ -221,9 +231,40 @@ def test_预警_审批超时命中且参数关闭后不产生(client: TestClient
def test_动态_来源操作日志(client: TestClient, admin: dict):
_chain(client, admin["headers"])
data = _dashboard(client, admin["headers"])
assert data["activities"], "工作台动态为空:写操作应产生操作日志"
assert {"module", "action", "summary", "create_time"} <= set(data["activities"][0])
data = _activities(client, admin["headers"])
assert data["list"], "工作台动态为空:写操作应产生操作日志"
assert {"module", "action", "summary", "create_time"} <= set(data["list"][0])
def test_动态_分页翻页不重不漏(client: TestClient, admin: dict):
_chain(client, admin["headers"])
first = _activities(client, admin["headers"], pageNum=1, pageSize=2)
assert first["pageNum"] == 1
assert first["pageSize"] == 2
assert len(first["list"]) == 2
assert first["total"] >= 2
second = _activities(client, admin["headers"], pageNum=2, pageSize=2)
assert len(second["list"]) == 2
# 两页不重不漏(倒序取,按 id 倒排)
first_ids = {item["id"] for item in first["list"]}
second_ids = {item["id"] for item in second["list"]}
assert first_ids.isdisjoint(second_ids)
assert first["list"][0]["id"] > second["list"][0]["id"]
def test_动态_模块筛选与筛选项(client: TestClient, admin: dict):
_chain(client, admin["headers"])
page = _activities(client, admin["headers"], pageSize=50)
assert page["modules"], "模块筛选项不应为空"
module = page["modules"][0]
filtered = _activities(client, admin["headers"], module=module, pageSize=50)
assert filtered["total"] >= 1
assert filtered["list"], "按模块筛选后应有数据"
assert all(item["module"] == module for item in filtered["list"])
# 筛选项不随筛选条件变化(下拉里始终是全量模块)
assert filtered["modules"] == page["modules"]
# ==== 角色待办 / 预警阈值 / 趋势(2026-10-19 code-review 修复回归)====