更新查询方式

This commit is contained in:
2026-01-08 19:33:42 +08:00
parent f6f50532a6
commit 61ddc96f17
13 changed files with 341 additions and 275 deletions

View File

@@ -8,11 +8,10 @@ from loguru import logger as l
from sqlalchemy import and_
from middleware.auth import admin_required
from middleware.dependencies import SessionDep
from middleware.dependencies import SessionDep, TableViewRequestDep
from models import (
Policy, PolicyType, User, ResponseBase,
Object, ObjectType, )
from models.object import AdminFileResponse, FileBanRequest
Policy, PolicyType, User, ResponseBase, ListResponse,
Object, ObjectType, AdminFileResponse, FileBanRequest, )
from service.storage import LocalStorageService
admin_file_router = APIRouter(
@@ -28,25 +27,21 @@ admin_file_router = APIRouter(
)
async def router_admin_get_file_list(
session: SessionDep,
table_view: TableViewRequestDep,
user_id: UUID | None = None,
is_banned: bool | None = None,
keyword: str | None = None,
page: int = 1,
page_size: int = 20,
) -> ResponseBase:
) -> ListResponse[AdminFileResponse]:
"""
获取系统中的文件列表,支持筛选。
:param session: 数据库会话
:param table_view: 分页排序参数依赖
:param user_id: 按用户筛选
:param is_banned: 按封禁状态筛选
:param keyword: 按文件名搜索
:param page: 页码
:param page_size: 每页数量
:return: 文件列表
:return: 分页文件列表
"""
offset = (page - 1) * page_size
# 构建查询条件
conditions = [Object.type == ObjectType.FILE]
if user_id:
@@ -56,42 +51,17 @@ async def router_admin_get_file_list(
if keyword:
conditions.append(Object.name.ilike(f"%{keyword}%"))
combined_condition = and_(*conditions) if len(conditions) > 1 else conditions[0]
files = await Object.get(
session,
combined_condition,
fetch_mode="all",
offset=offset,
limit=page_size,
load=Object.owner,
)
total = await Object.count(session, combined_condition)
condition = and_(*conditions) if len(conditions) > 1 else conditions[0]
result = await Object.get_with_count(session, condition, table_view=table_view, load=Object.owner)
# 构建响应
file_list = []
for f in files:
items: list[AdminFileResponse] = []
for f in result.items:
owner = await f.awaitable_attrs.owner
policy = await f.awaitable_attrs.policy
file_list.append(AdminFileResponse(
id=f.id,
name=f.name,
type=f.type,
size=f.size,
thumb=False,
date=f.updated_at,
create_date=f.created_at,
source_enabled=False,
owner_id=f.owner_id,
owner_username=owner.username if owner else "unknown",
policy_name=policy.name if policy else "unknown",
is_banned=f.is_banned,
banned_at=f.banned_at,
ban_reason=f.ban_reason,
).model_dump())
items.append(AdminFileResponse.from_object(f, owner, policy))
return ResponseBase(data={"files": file_list, "total": total})
return ListResponse(items=items, count=result.count)
@admin_file_router.get(

View File

@@ -4,9 +4,9 @@ from fastapi import APIRouter, Depends, HTTPException
from loguru import logger as l
from middleware.auth import admin_required
from middleware.dependencies import SessionDep
from middleware.dependencies import SessionDep, TableViewRequestDep
from models import (
User, ResponseBase,
User, ResponseBase, UserPublic, ListResponse,
Group, GroupOptions, )
from models.group import (
GroupCreateRequest, GroupUpdateRequest, GroupDetailResponse, )
@@ -25,61 +25,25 @@ admin_group_router = APIRouter(
)
async def router_admin_get_groups(
session: SessionDep,
page: int = 1,
page_size: int = 20,
) -> ResponseBase:
table_view: TableViewRequestDep,
) -> ListResponse[GroupDetailResponse]:
"""
获取用户组列表,支持分页。
获取用户组列表,支持分页、排序和时间筛选
:param session: 数据库会话
:param page: 页码
:param page_size: 每页数量
:return: 用户组列表
:param table_view: 分页排序参数依赖
:return: 分页用户组列表
"""
offset = (page - 1) * page_size
groups = await Group.get(
session,
None,
fetch_mode="all",
offset=offset,
limit=page_size,
load=Group.options,
)
total = await Group.count(session, None)
result = await Group.get_with_count(session, table_view=table_view, load=Group.options)
# 构建响应
group_list = []
for g in groups:
opts = g.options
items: list[GroupDetailResponse] = []
for g in result.items:
policies = await g.awaitable_attrs.policies
user_count = await User.count(session, User.group_id == g.id)
items.append(GroupDetailResponse.from_group(g, user_count, policies))
group_list.append(GroupDetailResponse(
id=g.id,
name=g.name,
max_storage=g.max_storage,
share_enabled=g.share_enabled,
web_dav_enabled=g.web_dav_enabled,
admin=g.admin,
speed_limit=g.speed_limit,
user_count=user_count,
policy_ids=[p.id for p in policies],
share_download=opts.share_download if opts else False,
share_free=opts.share_free if opts else False,
relocate=opts.relocate if opts else False,
source_batch=opts.source_batch if opts else 0,
select_node=opts.select_node if opts else False,
advance_delete=opts.advance_delete if opts else False,
archive_download=opts.archive_download if opts else False,
archive_task=opts.archive_task if opts else False,
webdav_proxy=opts.webdav_proxy if opts else False,
aria2=opts.aria2 if opts else False,
redirected_source=opts.redirected_source if opts else False,
).model_dump())
return ResponseBase(data={"groups": group_list, "total": total})
return ListResponse(items=items, count=result.count)
@admin_group_router.get(
@@ -104,32 +68,9 @@ async def router_admin_get_group(
if not group:
raise HTTPException(status_code=404, detail="用户组不存在")
opts = group.options
policies = await group.awaitable_attrs.policies
user_count = await User.count(session, User.group_id == group_id)
response = GroupDetailResponse(
id=group.id,
name=group.name,
max_storage=group.max_storage,
share_enabled=group.share_enabled,
web_dav_enabled=group.web_dav_enabled,
admin=group.admin,
speed_limit=group.speed_limit,
user_count=user_count,
policy_ids=[p.id for p in policies],
share_download=opts.share_download if opts else False,
share_free=opts.share_free if opts else False,
relocate=opts.relocate if opts else False,
source_batch=opts.source_batch if opts else 0,
select_node=opts.select_node if opts else False,
advance_delete=opts.advance_delete if opts else False,
archive_download=opts.archive_download if opts else False,
archive_task=opts.archive_task if opts else False,
webdav_proxy=opts.webdav_proxy if opts else False,
aria2=opts.aria2 if opts else False,
redirected_source=opts.redirected_source if opts else False,
)
response = GroupDetailResponse.from_group(group, user_count, policies)
return ResponseBase(data=response.model_dump())
@@ -143,40 +84,28 @@ async def router_admin_get_group(
async def router_admin_get_group_members(
session: SessionDep,
group_id: UUID,
page: int = 1,
page_size: int = 20,
) -> ResponseBase:
table_view: TableViewRequestDep,
) -> ListResponse[UserPublic]:
"""
根据用户组ID获取用户组成员列表。
:param session: 数据库会话
:param group_id: 用户组UUID
:param page: 页码
:param page_size: 每页数量
:return: 成员列表
:param table_view: 分页排序参数依赖
:return: 分页成员列表
"""
# 验证组存在
group = await Group.get(session, Group.id == group_id)
if not group:
raise HTTPException(status_code=404, detail="用户组不存在")
offset = (page - 1) * page_size
result = await User.get_with_count(session, User.group_id == group_id, table_view=table_view)
users = await User.get(
session,
User.group_id == group_id,
fetch_mode="all",
offset=offset,
limit=page_size,
return ListResponse(
items=[u.to_public() for u in result.items],
count=result.count,
)
total = await User.count(session, User.group_id == group_id)
return ResponseBase(data={
"members": [u.to_public().model_dump() for u in users],
"total": total,
})
@admin_group_router.post(
path='/',

View File

@@ -5,10 +5,10 @@ from loguru import logger as l
from sqlmodel import Field
from middleware.auth import admin_required
from middleware.dependencies import SessionDep
from middleware.dependencies import SessionDep, TableViewRequestDep
from models import (
Policy, PolicyBase, PolicyType, ResponseBase,
Object, )
Policy, PolicyBase, PolicyType, PolicySummary, ResponseBase,
ListResponse, Object, )
from models.base import SQLModelBase
from service.storage import DirectoryCreationError, LocalStorageService
@@ -45,44 +45,22 @@ class PolicyCreateRequest(PolicyBase):
)
async def router_policy_list(
session: SessionDep,
page: int = 1,
page_size: int = 20,
) -> ResponseBase:
table_view: TableViewRequestDep,
) -> ListResponse[PolicySummary]:
"""
获取所有存储策略列表。
:param session: 数据库会话
:param page: 页码
:param page_size: 每页数量
:return: 策略列表
:param table_view: 分页排序参数依赖
:return: 分页策略列表
"""
offset = (page - 1) * page_size
result = await Policy.get_with_count(session, table_view=table_view)
policies = await Policy.get(
session,
None,
fetch_mode="all",
offset=offset,
limit=page_size,
return ListResponse(
items=[PolicySummary.model_validate(p, from_attributes=True) for p in result.items],
count=result.count,
)
total = await Policy.count(session, None)
return ResponseBase(data={
"policies": [
{
"id": str(p.id),
"name": p.name,
"type": p.type.value,
"server": p.server,
"max_size": p.max_size,
"is_private": p.is_private,
}
for p in policies
],
"total": total,
})
@admin_policy_router.post(
path='/test/path',

View File

@@ -4,10 +4,10 @@ from fastapi import APIRouter, Depends, HTTPException
from loguru import logger as l
from middleware.auth import admin_required
from middleware.dependencies import SessionDep
from middleware.dependencies import SessionDep, TableViewRequestDep
from models import (
ResponseBase,
Share, )
ResponseBase, ListResponse,
Share, AdminShareListItem, )
admin_share_router = APIRouter(
prefix='/share',
@@ -22,53 +22,27 @@ admin_share_router = APIRouter(
)
async def router_admin_get_share_list(
session: SessionDep,
table_view: TableViewRequestDep,
user_id: UUID | None = None,
page: int = 1,
page_size: int = 20,
) -> ResponseBase:
) -> ListResponse[AdminShareListItem]:
"""
获取分享列表。
:param session: 数据库会话
:param table_view: 分页排序参数依赖
:param user_id: 按用户筛选
:param page: 页码
:param page_size: 每页数量
:return: 分享列表
:return: 分页分享列表
"""
offset = (page - 1) * page_size
condition = Share.user_id == user_id if user_id else None
result = await Share.get_with_count(session, condition, table_view=table_view, load=Share.user)
shares = await Share.get(
session,
condition,
fetch_mode="all",
offset=offset,
limit=page_size,
load=Share.user,
)
total = await Share.count(session, condition)
share_list = []
for s in shares:
items: list[AdminShareListItem] = []
for s in result.items:
user = await s.awaitable_attrs.user
obj = await s.awaitable_attrs.object
share_list.append({
"id": s.id,
"code": s.code,
"views": s.views,
"downloads": s.downloads,
"remain_downloads": s.remain_downloads,
"expires": s.expires.isoformat() if s.expires else None,
"preview_enabled": s.preview_enabled,
"score": s.score,
"user_id": str(s.user_id),
"username": user.username if user else None,
"object_name": obj.name if obj else None,
"created_at": s.created_at.isoformat(),
})
items.append(AdminShareListItem.from_share(s, user, obj))
return ResponseBase(data={"shares": share_list, "total": total})
return ListResponse(items=items, count=result.count)
@admin_share_router.get(

View File

@@ -5,10 +5,10 @@ from loguru import logger as l
from sqlalchemy import and_
from middleware.auth import admin_required
from middleware.dependencies import SessionDep
from middleware.dependencies import SessionDep, TableViewRequestDep
from models import (
ResponseBase,
Task,
ResponseBase, ListResponse,
Task, TaskSummary,
)
admin_task_router = APIRouter(
@@ -24,23 +24,19 @@ admin_task_router = APIRouter(
)
async def router_admin_get_task_list(
session: SessionDep,
table_view: TableViewRequestDep,
user_id: UUID | None = None,
status: str | None = None,
page: int = 1,
page_size: int = 20,
) -> ResponseBase:
) -> ListResponse[TaskSummary]:
"""
获取任务列表。
:param session: 数据库会话
:param table_view: 分页排序参数依赖
:param user_id: 按用户筛选
:param status: 按状态筛选
:param page: 页码
:param page_size: 每页数量
:return: 任务列表
:return: 分页任务列表
"""
offset = (page - 1) * page_size
conditions = []
if user_id:
conditions.append(Task.user_id == user_id)
@@ -48,34 +44,14 @@ async def router_admin_get_task_list(
conditions.append(Task.status == status)
condition = and_(*conditions) if conditions else None
result = await Task.get_with_count(session, condition, table_view=table_view, load=Task.user)
tasks = await Task.get(
session,
condition,
fetch_mode="all",
offset=offset,
limit=page_size,
load=Task.user,
)
total = await Task.count(session, condition)
task_list = []
for t in tasks:
items: list[TaskSummary] = []
for t in result.items:
user = await t.awaitable_attrs.user
task_list.append({
"id": t.id,
"status": t.status,
"type": t.type,
"progress": t.progress,
"error": t.error,
"user_id": str(t.user_id),
"username": user.username if user else None,
"created_at": t.created_at.isoformat(),
"updated_at": t.updated_at.isoformat(),
})
items.append(TaskSummary.from_task(t, user))
return ResponseBase(data={"tasks": task_list, "total": total})
return ListResponse(items=items, count=result.count)
@admin_task_router.get(

View File

@@ -5,9 +5,9 @@ from loguru import logger as l
from sqlalchemy import func, and_
from middleware.auth import admin_required
from middleware.dependencies import SessionDep
from middleware.dependencies import SessionDep, TableViewRequestDep
from models import (
User, ResponseBase,
User, ResponseBase, UserPublic, ListResponse,
Group, Object, ObjectType, )
from models.user import (
UserAdminUpdateRequest, UserCalibrateResponse,
@@ -49,30 +49,19 @@ async def router_admin_get_user(session: SessionDep, user_id: int) -> ResponseBa
)
async def router_admin_get_users(
session: SessionDep,
page: int = 1,
page_size: int = 20
) -> ResponseBase:
table_view: TableViewRequestDep,
) -> ListResponse[UserPublic]:
"""
获取用户列表,支持分页。
获取用户列表,支持分页、排序和时间筛选
Args:
session: 数据库会话依赖项。
page (int): 页码默认为1。
page_size (int): 每页显示的用户数量默认为20。
Returns:
ResponseBase: 包含用户列表的响应模型。
:param session: 数据库会话依赖项
:param table_view: 分页排序参数依赖
:return: 分页用户列表
"""
offset = (page - 1) * page_size
users: list[User] = await User.get(
session,
None,
fetch_mode="all",
offset=offset,
limit=page_size
)
return ResponseBase(
data=[user.to_public().model_dump() for user in users]
result = await User.get_with_count(session, table_view=table_view)
return ListResponse(
items=[user.to_public() for user in result.items],
count=result.count,
)