feat: 6 улучшений формы - S3 upload, draft, HEIC, email на step3
1. ✅ Placeholder с тире E1000-302538524 - Теперь в placeholder тоже тире 2. ✅ Email перенесен на Step3 - Убран с Step1 (проверка полиса) - Добавлен на Step3 (вместе с телефоном) - Теперь телефон + email + выплата на одном шаге 3. ✅ HEIC формат + мультилоад - Добавлена поддержка .heic, .heif (iPhone формат) - Убран maxCount - неограниченная загрузка - Параметр multiple для множественной загрузки 4. ✅ S3 Upload - Создан s3_service.py для работы с Timeweb S3 - Новый endpoint: POST /api/v1/upload/files - Поддержка мультизагрузки файлов - Автоматическая генерация уникальных имен - Файлы грузятся в S3, не локально 5. ✅ Draft автосохранение - Создана таблица claims_draft в PostgreSQL - Новый API: POST /api/v1/draft/save - GET /api/v1/draft/stats - статистика по шагам - GET /api/v1/draft/list - список последних драфтов - Для аналитики: где люди бросают заполнение 6. ✅ Миграция БД - 002_create_claims_draft.sql применена - Индексы для быстрого поиска - JSONB поле для гибкости данных Backend: - s3_service.py - сервис для S3 - draft.py - API автосохранения - upload.py - обновлен endpoint для S3 - main.py - добавлены роуты и подключения Frontend: - Step1Policy: убран email, добавлен HEIC - Step3Payment: добавлен email после телефона Статус: ✅ Backend подключен к S3, таблица создана, всё работает
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Upload API Routes - Загрузка файлов с OCR
|
||||
Upload API Routes - Загрузка файлов с OCR и S3
|
||||
"""
|
||||
from fastapi import APIRouter, UploadFile, File, HTTPException
|
||||
from typing import List
|
||||
@@ -7,6 +7,7 @@ import httpx
|
||||
import uuid
|
||||
import os
|
||||
from ..config import settings
|
||||
from ..services.s3_service import s3_service
|
||||
import logging
|
||||
|
||||
router = APIRouter(prefix="/api/v1/upload", tags=["Upload"])
|
||||
@@ -152,3 +153,67 @@ async def upload_passport(file: UploadFile = File(...)):
|
||||
logger.error(f"Passport upload error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.post("/files")
|
||||
async def upload_files(files: List[UploadFile] = File(...), folder: str = "claims"):
|
||||
"""
|
||||
Универсальная загрузка файлов в S3
|
||||
Поддерживает множественную загрузку
|
||||
|
||||
Args:
|
||||
files: Список файлов для загрузки
|
||||
folder: Папка в S3 (claims, policies, documents и т.д.)
|
||||
|
||||
Returns:
|
||||
List[dict]: Список загруженных файлов с URLs
|
||||
"""
|
||||
try:
|
||||
uploaded_files = []
|
||||
|
||||
for file in files:
|
||||
try:
|
||||
# Читаем содержимое файла
|
||||
content = await file.read()
|
||||
|
||||
# Загружаем в S3
|
||||
file_url = await s3_service.upload_file(
|
||||
file_content=content,
|
||||
filename=file.filename,
|
||||
content_type=file.content_type or 'application/octet-stream',
|
||||
folder=folder
|
||||
)
|
||||
|
||||
if file_url:
|
||||
uploaded_files.append({
|
||||
"success": True,
|
||||
"filename": file.filename,
|
||||
"url": file_url,
|
||||
"size": len(content),
|
||||
"content_type": file.content_type
|
||||
})
|
||||
else:
|
||||
uploaded_files.append({
|
||||
"success": False,
|
||||
"filename": file.filename,
|
||||
"error": "S3 upload failed"
|
||||
})
|
||||
|
||||
except Exception as file_error:
|
||||
logger.error(f"Error uploading {file.filename}: {file_error}")
|
||||
uploaded_files.append({
|
||||
"success": False,
|
||||
"filename": file.filename,
|
||||
"error": str(file_error)
|
||||
})
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"uploaded_count": len([f for f in uploaded_files if f.get("success")]),
|
||||
"total_count": len(files),
|
||||
"files": uploaded_files
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Batch upload error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user