160 lines
5.9 KiB
Python
160 lines
5.9 KiB
Python
"""笔记相关路由"""
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
from sqlalchemy.orm import Session
|
|
from models import get_db, Note
|
|
from middleware.user_context import UserContext
|
|
|
|
router = APIRouter(tags=["笔记"])
|
|
|
|
|
|
@router.get("/api/notes")
|
|
def list_notes(folder_id: int = None, db: Session = Depends(get_db), request: Request = None):
|
|
"""获取笔记列表(仅当前用户)"""
|
|
user_id = UserContext.get_user_id(request)
|
|
q = db.query(Note).filter(Note.created_by == user_id)
|
|
if folder_id:
|
|
q = q.filter(Note.folder_id == folder_id)
|
|
return q.order_by(Note.updated_at.desc()).all()
|
|
|
|
|
|
@router.post("/api/notes")
|
|
def create_note(data: dict, db: Session = Depends(get_db), request: Request = None):
|
|
"""创建笔记"""
|
|
user_id = UserContext.get_user_id(request)
|
|
note = Note(
|
|
title=data.get("title", "无标题"),
|
|
content=data.get("content", ""),
|
|
folder_id=data.get("folder_id"),
|
|
created_by=user_id,
|
|
updated_by=user_id,
|
|
)
|
|
db.add(note)
|
|
db.commit()
|
|
db.refresh(note)
|
|
return {"id": note.id, "title": note.title, "content": note.content,
|
|
"folder_id": note.folder_id, "created_by": note.created_by, "updated_by": note.updated_by,
|
|
"created_at": str(note.created_at), "updated_at": str(note.updated_at)}
|
|
|
|
|
|
@router.get("/api/notes/{note_id}")
|
|
def get_note(note_id: int, db: Session = Depends(get_db), request: Request = None):
|
|
"""获取单个笔记"""
|
|
user_id = UserContext.get_user_id(request)
|
|
note = db.query(Note).filter(Note.id == note_id, Note.created_by == user_id).first()
|
|
if not note:
|
|
raise HTTPException(404, "笔记不存在")
|
|
return {"id": note.id, "title": note.title, "content": note.content,
|
|
"folder_id": note.folder_id, "created_by": note.created_by, "updated_by": note.updated_by,
|
|
"created_at": str(note.created_at), "updated_at": str(note.updated_at)}
|
|
|
|
|
|
@router.put("/api/notes/{note_id}")
|
|
def update_note(note_id: int, data: dict, db: Session = Depends(get_db), request: Request = None):
|
|
"""更新笔记"""
|
|
user_id = UserContext.get_user_id(request)
|
|
note = db.query(Note).filter(Note.id == note_id, Note.created_by == user_id).first()
|
|
if not note:
|
|
raise HTTPException(404, "笔记不存在")
|
|
if "title" in data:
|
|
note.title = data["title"]
|
|
if "content" in data:
|
|
note.content = data["content"]
|
|
if "folder_id" in data:
|
|
note.folder_id = data["folder_id"]
|
|
note.updated_by = user_id
|
|
db.commit()
|
|
db.refresh(note)
|
|
return {"ok": True}
|
|
|
|
|
|
@router.delete("/api/notes/{note_id}")
|
|
def delete_note(note_id: int, db: Session = Depends(get_db), request: Request = None):
|
|
"""删除笔记"""
|
|
user_id = UserContext.get_user_id(request)
|
|
note = db.query(Note).filter(Note.id == note_id, Note.created_by == user_id).first()
|
|
if not note:
|
|
raise HTTPException(404, "笔记不存在")
|
|
db.delete(note)
|
|
db.commit()
|
|
return {"ok": True}
|
|
|
|
|
|
# ===== 分享 =====
|
|
import secrets
|
|
|
|
@router.post("/api/notes/{note_id}/share")
|
|
def share_note(note_id: int, data: dict = {}, db: Session = Depends(get_db), request: Request = None):
|
|
"""生成/刷新分享链接,可设置有效期"""
|
|
from datetime import datetime, timedelta
|
|
user_id = UserContext.get_user_id(request)
|
|
note = db.query(Note).filter(Note.id == note_id, Note.created_by == user_id).first()
|
|
if not note:
|
|
raise HTTPException(404, "笔记不存在")
|
|
note.share_token = secrets.token_urlsafe(16)
|
|
|
|
# 有效期: 7d / 30d / 1y / forever
|
|
ttl = data.get("ttl", "forever")
|
|
if ttl == "7d":
|
|
note.share_expires_at = datetime.utcnow() + timedelta(days=7)
|
|
elif ttl == "30d":
|
|
note.share_expires_at = datetime.utcnow() + timedelta(days=30)
|
|
elif ttl == "1y":
|
|
note.share_expires_at = datetime.utcnow() + timedelta(days=365)
|
|
else:
|
|
note.share_expires_at = None # 永久
|
|
|
|
db.commit()
|
|
return {
|
|
"share_token": note.share_token,
|
|
"url": f"/share/{note.share_token}",
|
|
"expires_at": note.share_expires_at.strftime("%Y-%m-%d %H:%M") if note.share_expires_at else "永久有效",
|
|
}
|
|
|
|
|
|
@router.delete("/api/notes/{note_id}/share")
|
|
def unshare_note(note_id: int, db: Session = Depends(get_db), request: Request = None):
|
|
"""取消分享"""
|
|
user_id = UserContext.get_user_id(request)
|
|
note = db.query(Note).filter(Note.id == note_id, Note.created_by == user_id).first()
|
|
if not note:
|
|
raise HTTPException(404, "笔记不存在")
|
|
note.share_token = None
|
|
db.commit()
|
|
return {"ok": True}
|
|
|
|
|
|
# ===== 移动 =====
|
|
@router.put("/api/notes/{note_id}/move")
|
|
def move_note(note_id: int, data: dict, db: Session = Depends(get_db), request: Request = None):
|
|
"""移动笔记到另一个文件夹"""
|
|
user_id = UserContext.get_user_id(request)
|
|
note = db.query(Note).filter(Note.id == note_id, Note.created_by == user_id).first()
|
|
if not note:
|
|
raise HTTPException(404, "笔记不存在")
|
|
note.folder_id = data.get("folder_id")
|
|
db.commit()
|
|
return {"ok": True, "folder_id": note.folder_id}
|
|
|
|
|
|
# ===== 分享管理 =====
|
|
@router.get("/api/shares")
|
|
def list_shares(db: Session = Depends(get_db), request: Request = None):
|
|
"""列出当前用户已分享的笔记"""
|
|
user_id = UserContext.get_user_id(request)
|
|
notes = db.query(Note).filter(
|
|
Note.share_token.isnot(None),
|
|
Note.created_by == user_id,
|
|
).order_by(Note.updated_at.desc()).all()
|
|
result = []
|
|
for n in notes:
|
|
result.append({
|
|
"id": n.id,
|
|
"title": n.title,
|
|
"share_token": n.share_token,
|
|
"share_url": f"/share/{n.share_token}",
|
|
"share_expires_at": n.share_expires_at.strftime("%Y-%m-%d %H:%M") if n.share_expires_at else "永久有效",
|
|
"created_by": n.created_by,
|
|
"updated_at": str(n.updated_at),
|
|
})
|
|
return result
|