Files
ai-app-database/app/routes/folders.py
T
huty f3bd3f68a5
CI — Docker Build & Push / Build & Push Image (push) Failing after 10m15s
新增文件夹功能
2026-04-23 15:45:28 +09:00

144 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from flask import Blueprint, jsonify, request, abort
from flask_login import login_required, current_user
from app.extensions import db
from app.models.folder import Folder
from app.utils.file_handler import delete_resource_file
folders_bp = Blueprint('folders', __name__)
# ── 递归删除辅助函数 ──────────────────────────────────────────────────────────
def _delete_folder_recursive(folder: Folder):
"""DFS 递归删除文件夹:先删子文件夹,再删资源(含磁盘文件),最后删自身"""
for child in list(folder.children):
_delete_folder_recursive(child)
for res in folder.resources.all():
delete_resource_file(res.file_path)
db.session.delete(res)
db.session.delete(folder)
# ── 路由 ──────────────────────────────────────────────────────────────────────
@folders_bp.route('/tree')
@login_required
def tree():
"""返回当前用户的完整文件夹树(JSON"""
return jsonify(Folder.get_user_tree(current_user.id))
@folders_bp.route('/create', methods=['POST'])
@login_required
def create():
"""创建文件夹"""
name = request.form.get('name', '').strip()
parent_id_raw = request.form.get('parent_id', '').strip()
parent_id = int(parent_id_raw) if parent_id_raw.isdigit() else None
if not name or len(name) > 128:
return jsonify(ok=False, msg='文件夹名称无效(1-128位)'), 400
# 验证父文件夹归属
if parent_id is not None:
parent = db.session.get(Folder, parent_id)
if parent is None or parent.user_id != current_user.id:
abort(403)
# 同级重名校验(覆盖 NULL parent_id 场景)
dup = Folder.query.filter_by(
user_id=current_user.id,
parent_id=parent_id,
name=name
).first()
if dup:
return jsonify(ok=False, msg='该位置已存在同名文件夹'), 409
folder = Folder(user_id=current_user.id, name=name, parent_id=parent_id)
db.session.add(folder)
db.session.commit()
return jsonify(ok=True, folder={
'id': folder.id, 'name': folder.name,
'parent_id': folder.parent_id, 'resource_count': 0, 'children': []
})
@folders_bp.route('/<int:folder_id>/rename', methods=['POST'])
@login_required
def rename(folder_id):
"""重命名文件夹"""
folder = db.session.get(Folder, folder_id)
if folder is None or folder.user_id != current_user.id:
abort(403)
name = request.form.get('name', '').strip()
if not name or len(name) > 128:
return jsonify(ok=False, msg='文件夹名称无效'), 400
if name == folder.name:
return jsonify(ok=True)
# 同级重名校验
dup = Folder.query.filter_by(
user_id=current_user.id,
parent_id=folder.parent_id,
name=name
).filter(Folder.id != folder_id).first()
if dup:
return jsonify(ok=False, msg='该位置已存在同名文件夹'), 409
folder.name = name
db.session.commit()
return jsonify(ok=True)
@folders_bp.route('/<int:folder_id>/delete', methods=['POST'])
@login_required
def delete(folder_id):
"""递归删除文件夹(含所有子文件夹和资源)"""
folder = db.session.get(Folder, folder_id)
if folder is None or folder.user_id != current_user.id:
abort(403)
_delete_folder_recursive(folder)
db.session.commit()
return jsonify(ok=True)
@folders_bp.route('/<int:folder_id>/move', methods=['POST'])
@login_required
def move(folder_id):
"""移动文件夹到新的父文件夹"""
folder = db.session.get(Folder, folder_id)
if folder is None or folder.user_id != current_user.id:
abort(403)
parent_id_raw = request.form.get('parent_id', '').strip()
new_parent_id = int(parent_id_raw) if parent_id_raw.isdigit() else None
if new_parent_id is not None:
# 不能移动到自身
if new_parent_id == folder_id:
return jsonify(ok=False, msg='不能将文件夹移动到自身'), 400
# 不能移动到自己的子孙节点
if folder.is_ancestor_of(new_parent_id):
return jsonify(ok=False, msg='不能将文件夹移动到其子文件夹中'), 400
# 验证目标父文件夹归属
new_parent = db.session.get(Folder, new_parent_id)
if new_parent is None or new_parent.user_id != current_user.id:
abort(403)
# 同级重名校验
dup = Folder.query.filter_by(
user_id=current_user.id,
parent_id=new_parent_id,
name=folder.name
).filter(Folder.id != folder_id).first()
if dup:
return jsonify(ok=False, msg='目标位置已有同名文件夹'), 409
folder.parent_id = new_parent_id
db.session.commit()
return jsonify(ok=True)