mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-06-25 17:23:59 +08:00
feat: add recent files backend APIs (#119)
This commit is contained in:
@@ -19,12 +19,14 @@ from domain.audit import api as audit
|
||||
from domain.permission import api as permission
|
||||
from domain.user import api as user
|
||||
from domain.role import api as role
|
||||
from domain.recent_files import api as recent_files
|
||||
|
||||
|
||||
def include_routers(app: FastAPI):
|
||||
app.include_router(adapters.router)
|
||||
app.include_router(search_api.router)
|
||||
app.include_router(virtual_fs.router)
|
||||
app.include_router(recent_files.router)
|
||||
app.include_router(auth.router)
|
||||
app.include_router(config.router)
|
||||
app.include_router(processors.router)
|
||||
|
||||
3
domain/recent_files/__init__.py
Normal file
3
domain/recent_files/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .api import router
|
||||
|
||||
__all__ = ["router"]
|
||||
44
domain/recent_files/api.py
Normal file
44
domain/recent_files/api.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, Query, Request
|
||||
|
||||
from api.response import success
|
||||
from domain.audit import AuditAction, audit
|
||||
from domain.auth import User, get_current_active_user
|
||||
|
||||
from .service import RecentFilesService
|
||||
from .types import RecordRecentFileRequest
|
||||
|
||||
router = APIRouter(prefix="/api/fs/recent", tags=["recent-files"])
|
||||
|
||||
|
||||
@router.get("/")
|
||||
@audit(action=AuditAction.READ, description="查看最近打开文件")
|
||||
async def list_recent_files(
|
||||
request: Request,
|
||||
current_user: Annotated[User, Depends(get_current_active_user)],
|
||||
limit: int = Query(20, ge=1, le=200, description="返回数量"),
|
||||
):
|
||||
data = await RecentFilesService.list_recent_files(current_user.id, limit)
|
||||
return success(data)
|
||||
|
||||
|
||||
@router.post("/")
|
||||
@audit(action=AuditAction.CREATE, description="记录最近打开文件", body_fields=["path"])
|
||||
async def record_recent_file(
|
||||
request: Request,
|
||||
body: RecordRecentFileRequest,
|
||||
current_user: Annotated[User, Depends(get_current_active_user)],
|
||||
):
|
||||
data = await RecentFilesService.record_opened_file(current_user.id, body.path)
|
||||
return success(data)
|
||||
|
||||
|
||||
@router.delete("/")
|
||||
@audit(action=AuditAction.DELETE, description="清空最近打开文件")
|
||||
async def clear_recent_files(
|
||||
request: Request,
|
||||
current_user: Annotated[User, Depends(get_current_active_user)],
|
||||
):
|
||||
data = await RecentFilesService.clear_recent_files(current_user.id)
|
||||
return success(data)
|
||||
23
domain/recent_files/service.py
Normal file
23
domain/recent_files/service.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from models.database import RecentFile
|
||||
|
||||
|
||||
class RecentFilesService:
|
||||
@staticmethod
|
||||
async def record_opened_file(user_id: int, path: str) -> dict:
|
||||
item, created = await RecentFile.get_or_create(user_id=user_id, path=path)
|
||||
if not created:
|
||||
await RecentFile.filter(id=item.id).update(opened_at=datetime.now(timezone.utc))
|
||||
await item.fetch_from_db()
|
||||
return {"id": item.id, "path": item.path, "opened_at": item.opened_at.isoformat()}
|
||||
|
||||
@staticmethod
|
||||
async def list_recent_files(user_id: int, limit: int) -> list[dict]:
|
||||
items = await RecentFile.filter(user_id=user_id).order_by("-opened_at").limit(limit)
|
||||
return [{"id": i.id, "path": i.path, "opened_at": i.opened_at.isoformat()} for i in items]
|
||||
|
||||
@staticmethod
|
||||
async def clear_recent_files(user_id: int) -> dict:
|
||||
deleted = await RecentFile.filter(user_id=user_id).delete()
|
||||
return {"deleted": deleted}
|
||||
11
domain/recent_files/types.py
Normal file
11
domain/recent_files/types.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class RecordRecentFileRequest(BaseModel):
|
||||
path: str = Field(..., min_length=1, max_length=4096, description="文件完整路径")
|
||||
|
||||
|
||||
class RecentFileItem(BaseModel):
|
||||
id: int
|
||||
path: str
|
||||
opened_at: str
|
||||
@@ -234,6 +234,19 @@ class ShareLink(Model):
|
||||
table = "share_links"
|
||||
|
||||
|
||||
class RecentFile(Model):
|
||||
id = fields.IntField(pk=True)
|
||||
user: fields.ForeignKeyRelation[UserAccount] = fields.ForeignKeyField(
|
||||
"models.UserAccount", related_name="recent_files", on_delete=fields.CASCADE
|
||||
)
|
||||
path = fields.CharField(max_length=4096)
|
||||
opened_at = fields.DatetimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
table = "recent_files"
|
||||
unique_together = (("user", "path"),)
|
||||
|
||||
|
||||
class Plugin(Model):
|
||||
id = fields.IntField(pk=True)
|
||||
key = fields.CharField(max_length=100, unique=True) # 插件唯一标识
|
||||
|
||||
Reference in New Issue
Block a user