You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.2 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
文件目录服务
"""
from __future__ import annotations
from typing import Optional, List
from sqlalchemy import select
from iti.applications.extensions import db
from iti.applications.models import SysFileDirectory
from iti.applications.common.enums import StatusEnum
from iti.applications.common.exceptions.biz_exp import BizException
def init_app(app):
"""初始化文件目录(系统启动时自动执行)"""
with app.app_context():
try:
SysFileDirectoryService.ensure_default_directory()
except Exception as e:
print(f"⚠️ 默认目录初始化失败: {e}")
class SysFileDirectoryService:
"""文件目录服务"""
# 默认目录固定ID使用标准UUID格式
DEFAULT_DIRECTORY_ID = "00000000000000000000000000000001"
@classmethod
def ensure_default_directory(cls) -> SysFileDirectory:
"""
确保默认目录存在
Returns:
默认目录对象
"""
# 使用固定ID查找默认目录
default_dir = db.session.get(SysFileDirectory, cls.DEFAULT_DIRECTORY_ID)
if not default_dir:
# 创建默认目录使用固定ID
default_dir = SysFileDirectory(
id=cls.DEFAULT_DIRECTORY_ID,
name="默认目录",
path="/default",
parent_id=None,
level=0,
sort=0,
icon="folder",
description="系统默认文件目录",
status=StatusEnum.ENABLED,
)
db.session.add(default_dir)
db.session.commit()
return default_dir
@classmethod
def get_default_directory_id(cls) -> str:
"""
获取默认目录ID直接返回固定ID无需查询数据库
Returns:
默认目录ID
"""
return cls.DEFAULT_DIRECTORY_ID
@classmethod
def create_directory(
cls,
name: str,
parent_id: Optional[str] = None,
icon: Optional[str] = None,
color: Optional[str] = None,
description: Optional[str] = None,
) -> SysFileDirectory:
"""
创建目录
Args:
name: 目录名称
parent_id: 父目录ID
icon: 图标
color: 颜色
description: 描述
Returns:
目录对象
"""
# 计算路径和层级
if parent_id:
parent = db.session.get(SysFileDirectory, parent_id)
if not parent:
raise BizException("父目录不存在", code=404)
path = f"{parent.path}/{name}"
level = parent.level + 1
else:
path = f"/{name}"
level = 0
# 检查路径是否已存在
existing = db.session.scalar(select(SysFileDirectory).filter_by(path=path))
if existing:
raise BizException("目录路径已存在", code=400)
directory = SysFileDirectory(
name=name,
path=path,
parent_id=parent_id,
level=level,
sort=0,
icon=icon,
color=color,
description=description,
status=StatusEnum.ENABLED,
)
db.session.add(directory)
db.session.commit()
return directory
@classmethod
def get_directory_tree(
cls, parent_id: Optional[str] = None
) -> List[SysFileDirectory]:
"""
获取目录树
Args:
parent_id: 父目录IDNone表示获取根目录
Returns:
目录列表
"""
query = (
select(SysFileDirectory)
.filter_by(parent_id=parent_id, status=StatusEnum.ENABLED)
.order_by(SysFileDirectory.sort, SysFileDirectory.created_at)
)
directories = db.session.scalars(query).all()
return list(directories)
@classmethod
def delete_directory(cls, directory_id: str, force: bool = False) -> None:
"""
删除目录
Args:
directory_id: 目录ID
force: 是否强制删除(包括子目录和文件)
"""
directory = db.session.get(SysFileDirectory, directory_id)
if not directory:
raise BizException("目录不存在", code=404)
# 检查是否为默认目录
if directory.path == "/default":
raise BizException("不能删除默认目录", code=403)
if not force:
# 检查是否有子目录
has_children = db.session.scalar(
select(SysFileDirectory).filter_by(parent_id=directory_id).exists()
)
if has_children:
raise BizException("目录下有子目录,无法删除", code=400)
# 检查是否有文件
from iti.applications.models import SysFile
has_files = db.session.scalar(
select(SysFile).filter_by(directory_id=directory_id).exists()
)
if has_files:
raise BizException("目录下有文件,无法删除", code=400)
# 删除目录
db.session.delete(directory)
db.session.commit()