Files
s2f/backend/app/services/file_storage.py
T
freedakgmail 33b4c734aa feat: 完善前后端核心功能模块
后端:
- 新增认证(auth)、任务(tasks)、映射(mappings)、对账(reconciliation)、异常(exceptions)、导出(exports) API
- 新增核心模块: database, security, permissions, tenant, exceptions, error_handlers
- 新增数据模型: user, company, reconciliation_task, field_mapping, uploaded_file 等
- 新增服务层: ai_recognizer, file_parser, file_storage, mapping, reconciliation 等
- 添加数据库迁移脚本

前端:
- 新增登录页面和仪表盘页面
- 新增任务列表、任务详情、字段映射页面
- 新增异常处理页面和规则设置页面
- 新增 API 代理路由 /api/[...path]
- 新增 UI 组件库 (button, card, dialog, input, table 等)
- 新增 auth 组件 (ProtectedRoute, PermissionGate)
- 新增 layout 组件 (Header, Sidebar)
- 新增 mapping 组件 (FieldMappingTable, AISuggestionPanel)
- 新增 API 客户端和 hooks (useAsync, useToast, usePermission 等)
- 新增状态管理 (auth-store, company-store, ui-store)
- 集成 Tailwind CSS 和 shadcn/ui 组件库

其他:
- 添加 Alembic 数据库迁移配置
- 添加初始化示例数据脚本
- 更新项目文档
2026-07-07 09:04:47 +08:00

87 lines
2.2 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.
import os
import uuid
from pathlib import Path
from fastapi import UploadFile
from app.core.config import get_settings
settings = get_settings()
class FileStorageService:
"""文件存储服务"""
@staticmethod
def get_upload_dir() -> Path:
"""获取上传目录"""
upload_dir = Path(settings.upload_dir)
upload_dir.mkdir(parents=True, exist_ok=True)
return upload_dir
@staticmethod
async def save_file(file: UploadFile, company_id: int) -> tuple[str, int]:
"""
保存上传的文件
Args:
file: 上传的文件
company_id: 企业ID
Returns:
(存储文件名, 文件大小)
"""
# 创建企业专属目录
company_dir = FileStorageService.get_upload_dir() / str(company_id)
company_dir.mkdir(parents=True, exist_ok=True)
# 生成唯一文件名
file_ext = Path(file.filename or "file").suffix
stored_filename = f"{uuid.uuid4().hex}{file_ext}"
file_path = company_dir / stored_filename
# 保存文件
content = await file.read()
file_size = len(content)
with open(file_path, "wb") as f:
f.write(content)
return f"{company_id}/{stored_filename}", file_size
@staticmethod
def get_file_path(stored_filename: str) -> Path:
"""
获取文件完整路径
Args:
stored_filename: 存储文件名(格式: company_id/filename
Returns:
文件路径
"""
return FileStorageService.get_upload_dir() / stored_filename
@staticmethod
def delete_file(stored_filename: str) -> bool:
"""
删除文件
Args:
stored_filename: 存储文件名
Returns:
是否删除成功
"""
try:
file_path = FileStorageService.get_file_path(stored_filename)
if file_path.exists():
file_path.unlink()
return True
return False
except Exception:
return False
# 单例实例
file_storage_service = FileStorageService()