feat(admin/users): 用户列表支持列排序 + 渠道/昵称/时间范围筛选
list_users 由 keyset 游标改为 offset 分页以支持任意列排序:
- 排序:sort_by ∈ {id, created_at, last_login_at} + sort_order(白名单,非法回落 id;同值 id 同向兜底)
- 筛选:新增 nickname 模糊、注册/最近登录时间范围(register_channel 本就支持,这次在 UI/文档补齐)
- 文档 admin-users-list.md 与 test_admin_read 同步(排序/渠道/昵称/时间范围/非法 sort_by 422)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,80 @@ def test_user_filter_by_status(admin_client: TestClient, admin_token: str) -> No
|
||||
assert all(u["status"] == "active" for u in r.json()["items"])
|
||||
|
||||
|
||||
def test_user_list_sort_filter_range(admin_client: TestClient, admin_token: str) -> None:
|
||||
"""用户列表:渠道/昵称筛选 + id 升降序 + 时间范围 + 非法 sort_by 422。"""
|
||||
db = SessionLocal()
|
||||
try:
|
||||
u1 = user_repo.upsert_user_for_login(db, phone="13811110001", register_channel="sms")
|
||||
u1.nickname = "排序测试甲"
|
||||
u2 = user_repo.upsert_user_for_login(db, phone="13811110002", register_channel="wechat")
|
||||
u2.nickname = "排序测试乙"
|
||||
db.commit()
|
||||
id1, id2 = u1.id, u2.id
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
# 渠道精确筛选
|
||||
r = admin_client.get(
|
||||
"/admin/api/users", params={"register_channel": "wechat"}, headers=_auth(admin_token)
|
||||
)
|
||||
assert r.status_code == 200, r.text
|
||||
assert all(u["register_channel"] == "wechat" for u in r.json()["items"])
|
||||
|
||||
# 昵称模糊筛选
|
||||
r = admin_client.get(
|
||||
"/admin/api/users", params={"nickname": "排序测试", "limit": 100}, headers=_auth(admin_token)
|
||||
)
|
||||
ids = {u["id"] for u in r.json()["items"]}
|
||||
assert id1 in ids and id2 in ids
|
||||
|
||||
# id 升序 / 降序
|
||||
asc_ids = [
|
||||
u["id"]
|
||||
for u in admin_client.get(
|
||||
"/admin/api/users",
|
||||
params={"sort_by": "id", "sort_order": "asc", "limit": 100},
|
||||
headers=_auth(admin_token),
|
||||
).json()["items"]
|
||||
]
|
||||
assert asc_ids == sorted(asc_ids)
|
||||
desc_ids = [
|
||||
u["id"]
|
||||
for u in admin_client.get(
|
||||
"/admin/api/users",
|
||||
params={"sort_by": "id", "sort_order": "desc", "limit": 100},
|
||||
headers=_auth(admin_token),
|
||||
).json()["items"]
|
||||
]
|
||||
assert desc_ids == sorted(desc_ids, reverse=True)
|
||||
|
||||
# 时间范围:2000 年之前无人;之后有人(验证范围条件确实生效)
|
||||
assert (
|
||||
admin_client.get(
|
||||
"/admin/api/users", params={"created_to": "2000-01-01T00:00:00Z"},
|
||||
headers=_auth(admin_token),
|
||||
).json()["items"]
|
||||
== []
|
||||
)
|
||||
assert (
|
||||
len(
|
||||
admin_client.get(
|
||||
"/admin/api/users", params={"created_from": "2000-01-01T00:00:00Z", "limit": 100},
|
||||
headers=_auth(admin_token),
|
||||
).json()["items"]
|
||||
)
|
||||
>= 1
|
||||
)
|
||||
|
||||
# 非法 sort_by → 422
|
||||
assert (
|
||||
admin_client.get(
|
||||
"/admin/api/users", params={"sort_by": "phone"}, headers=_auth(admin_token)
|
||||
).status_code
|
||||
== 422
|
||||
)
|
||||
|
||||
|
||||
def test_wallet_and_withdraw_lists(admin_client: TestClient, admin_token: str) -> None:
|
||||
uid = _seed_user_with_data("13800000004")
|
||||
r = admin_client.get(
|
||||
|
||||
Reference in New Issue
Block a user