""" 文件目录服务 """ 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: 父目录ID,None表示获取根目录 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()