feat: 合并 File 和 Folder 模型为统一的 Object 模型,优化对象管理逻辑
refactor: 更新相关模型和路由以支持新对象模型,移除冗余代码
This commit is contained in:
@@ -1,45 +1,148 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from middleware.auth import SignRequired
|
||||
from models import response
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from middleware.auth import AuthRequired
|
||||
from middleware.dependencies import SessionDep
|
||||
from models import Object, ObjectType, User, response
|
||||
|
||||
directory_router = APIRouter(
|
||||
prefix="/directory",
|
||||
tags=["directory"]
|
||||
)
|
||||
|
||||
@directory_router.put(
|
||||
path='/',
|
||||
summary='创建目录',
|
||||
description='Create a directory endpoint.',
|
||||
dependencies=[Depends(SignRequired)]
|
||||
)
|
||||
def router_directory_create() -> response.ResponseModel:
|
||||
"""
|
||||
Create a directory endpoint.
|
||||
|
||||
Returns:
|
||||
ResponseModel: A model containing the response data for the directory creation.
|
||||
"""
|
||||
pass
|
||||
|
||||
class DirectoryCreateRequest(BaseModel):
|
||||
"""创建目录请求"""
|
||||
|
||||
path: str
|
||||
"""目录路径,如 /docs/images"""
|
||||
|
||||
policy_id: int | None = None
|
||||
"""存储策略ID,不指定则继承父目录"""
|
||||
|
||||
@directory_router.get(
|
||||
path='/{path:path}',
|
||||
summary='获取目录内容',
|
||||
description='Get directory contents endpoint.',
|
||||
dependencies=[Depends(SignRequired)]
|
||||
path="/{path:path}",
|
||||
summary="获取目录内容",
|
||||
)
|
||||
def router_directory_get(path: str) -> response.ResponseModel:
|
||||
async def router_directory_get(
|
||||
session: SessionDep,
|
||||
user: Annotated[User, Depends(AuthRequired)],
|
||||
path: str = ""
|
||||
) -> response.ResponseModel:
|
||||
"""
|
||||
Get directory contents endpoint.
|
||||
|
||||
Args:
|
||||
path (str): The path of the directory to retrieve contents from.
|
||||
|
||||
Returns:
|
||||
ResponseModel: A model containing the response data for the directory contents.
|
||||
获取目录内容
|
||||
|
||||
:param session: 数据库会话
|
||||
:param user: 当前登录用户
|
||||
:param path: 目录路径,空或 "/" 表示根目录
|
||||
:return: 目录内容
|
||||
"""
|
||||
folder = await Object.get_by_path(session, user.id, path or "/")
|
||||
|
||||
if not folder:
|
||||
raise HTTPException(status_code=404, detail="目录不存在")
|
||||
|
||||
if not folder.is_folder:
|
||||
raise HTTPException(status_code=400, detail="指定路径不是目录")
|
||||
|
||||
children = await Object.get_children(session, user.id, folder.id)
|
||||
policy = await folder.awaitable_attrs.policy
|
||||
|
||||
objects = [
|
||||
response.ObjectModel(
|
||||
id=str(child.id),
|
||||
name=child.name,
|
||||
path=f"/{child.name}", # TODO: 完整路径
|
||||
thumb=False,
|
||||
size=child.size,
|
||||
type="folder" if child.is_folder else "file",
|
||||
date=child.updated_at,
|
||||
create_date=child.created_at,
|
||||
source_enabled=False,
|
||||
)
|
||||
for child in children
|
||||
]
|
||||
|
||||
return response.ResponseModel(
|
||||
data=response.DirectoryModel(
|
||||
|
||||
parent=str(folder.parent_id) if folder.parent_id else None,
|
||||
objects=objects,
|
||||
policy=response.PolicyModel(
|
||||
id=str(policy.id),
|
||||
name=policy.name,
|
||||
type=policy.type.value,
|
||||
max_size=policy.max_size,
|
||||
file_type=[],
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@directory_router.put(
|
||||
path="/",
|
||||
summary="创建目录",
|
||||
)
|
||||
async def router_directory_create(
|
||||
session: SessionDep,
|
||||
user: Annotated[User, Depends(AuthRequired)],
|
||||
request: DirectoryCreateRequest
|
||||
) -> response.ResponseModel:
|
||||
"""
|
||||
创建目录
|
||||
|
||||
:param session: 数据库会话
|
||||
:param user: 当前登录用户
|
||||
:param request: 创建请求
|
||||
:return: 创建结果
|
||||
"""
|
||||
path = request.path.strip()
|
||||
if not path or path == "/":
|
||||
raise HTTPException(status_code=400, detail="路径不能为空或根目录")
|
||||
|
||||
# 解析路径
|
||||
if path.startswith("/"):
|
||||
path = path[1:]
|
||||
parts = [p for p in path.split("/") if p]
|
||||
|
||||
if not parts:
|
||||
raise HTTPException(status_code=400, detail="无效的目录路径")
|
||||
|
||||
new_folder_name = parts[-1]
|
||||
parent_path = "/" + "/".join(parts[:-1]) if len(parts) > 1 else "/"
|
||||
|
||||
parent = await Object.get_by_path(session, user.id, parent_path)
|
||||
if not parent:
|
||||
raise HTTPException(status_code=404, detail="父目录不存在")
|
||||
|
||||
if not parent.is_folder:
|
||||
raise HTTPException(status_code=400, detail="父路径不是目录")
|
||||
|
||||
# 检查是否已存在同名对象
|
||||
existing = await Object.get(
|
||||
session,
|
||||
(Object.owner_id == user.id) &
|
||||
(Object.parent_id == parent.id) &
|
||||
(Object.name == new_folder_name)
|
||||
)
|
||||
if existing:
|
||||
raise HTTPException(status_code=409, detail="同名文件或目录已存在")
|
||||
|
||||
policy_id = request.policy_id if request.policy_id else parent.policy_id
|
||||
|
||||
new_folder = await Object(
|
||||
name=new_folder_name,
|
||||
type=ObjectType.FOLDER,
|
||||
owner_id=user.id,
|
||||
parent_id=parent.id,
|
||||
policy_id=policy_id,
|
||||
).save(session)
|
||||
|
||||
return response.ResponseModel(
|
||||
data={
|
||||
"id": new_folder.id,
|
||||
"name": new_folder.name,
|
||||
"path": f"{parent_path.rstrip('/')}/{new_folder_name}",
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user