mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
2901-zustend для стора. сохранение черновиков построчно
редактор xml пока не работает, но есть ui переработал
This commit is contained in:
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -11,15 +12,20 @@ import (
|
||||
"go.uber.org/zap"
|
||||
|
||||
"rmser/internal/services/drafts"
|
||||
"rmser/internal/services/ocr"
|
||||
"rmser/pkg/logger"
|
||||
)
|
||||
|
||||
type DraftsHandler struct {
|
||||
service *drafts.Service
|
||||
service *drafts.Service
|
||||
ocrService *ocr.Service
|
||||
}
|
||||
|
||||
func NewDraftsHandler(service *drafts.Service) *DraftsHandler {
|
||||
return &DraftsHandler{service: service}
|
||||
func NewDraftsHandler(service *drafts.Service, ocrService *ocr.Service) *DraftsHandler {
|
||||
return &DraftsHandler{
|
||||
service: service,
|
||||
ocrService: ocrService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *DraftsHandler) GetDraft(c *gin.Context) {
|
||||
@@ -354,3 +360,54 @@ func (h *DraftsHandler) ReorderItems(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
|
||||
// Upload обрабатывает загрузку файла и прогоняет через OCR
|
||||
func (h *DraftsHandler) Upload(c *gin.Context) {
|
||||
// Лимит размера тела запроса (20MB)
|
||||
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 20<<20)
|
||||
|
||||
// Получаем файл из формы
|
||||
fileHeader, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "file is required"})
|
||||
return
|
||||
}
|
||||
|
||||
// Открываем файл для чтения
|
||||
file, err := fileHeader.Open()
|
||||
if err != nil {
|
||||
logger.Log.Error("Failed to open uploaded file", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to open file"})
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Читаем байты файла
|
||||
fileBytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
logger.Log.Error("Failed to read file bytes", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read file"})
|
||||
return
|
||||
}
|
||||
|
||||
// Получаем userID из контекста
|
||||
userID := c.MustGet("userID").(uuid.UUID)
|
||||
|
||||
// Вызываем ProcessDocument
|
||||
draft, err := h.ocrService.ProcessDocument(c.Request.Context(), userID, fileBytes, fileHeader.Filename)
|
||||
if err != nil {
|
||||
// Если черновик создан, но произошла ошибка OCR, возвращаем черновик со статусом ERROR
|
||||
// Проверяем, что draft не nil (черновик был создан)
|
||||
if draft != nil {
|
||||
c.JSON(http.StatusOK, draft)
|
||||
return
|
||||
}
|
||||
// Если черновик не был создан, возвращаем ошибку
|
||||
logger.Log.Error("ProcessDocument failed", zap.Error(err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Успешная обработка
|
||||
c.JSON(http.StatusOK, draft)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ type SettingsHandler struct {
|
||||
accountRepo account.Repository
|
||||
catalogRepo catalog.Repository
|
||||
notifier Notifier // Поле для отправки уведомлений
|
||||
rmsFactory RMSFactory
|
||||
}
|
||||
|
||||
type RMSFactory interface {
|
||||
ClearCacheForUser(userID uuid.UUID)
|
||||
}
|
||||
|
||||
func NewSettingsHandler(accRepo account.Repository, catRepo catalog.Repository) *SettingsHandler {
|
||||
@@ -31,6 +36,11 @@ func NewSettingsHandler(accRepo account.Repository, catRepo catalog.Repository)
|
||||
}
|
||||
}
|
||||
|
||||
// SetRMSFactory используется для внедрения зависимости после инициализации
|
||||
func (h *SettingsHandler) SetRMSFactory(f RMSFactory) {
|
||||
h.rmsFactory = f
|
||||
}
|
||||
|
||||
// SetNotifier используется для внедрения зависимости после инициализации
|
||||
func (h *SettingsHandler) SetNotifier(n Notifier) {
|
||||
h.notifier = n
|
||||
@@ -388,3 +398,107 @@ func (h *SettingsHandler) RemoveUser(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "removed"})
|
||||
}
|
||||
|
||||
// --- Server Management ---
|
||||
|
||||
// ServerShortDTO - краткая информация о сервере для списка
|
||||
type ServerShortDTO struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Role string `json:"role"` // OWNER, ADMIN, OPERATOR
|
||||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
|
||||
// GetUserServers возвращает список всех серверов пользователя с ролями и флагом активности
|
||||
func (h *SettingsHandler) GetUserServers(c *gin.Context) {
|
||||
userID := c.MustGet("userID").(uuid.UUID)
|
||||
|
||||
servers, err := h.accountRepo.GetAllAvailableServers(userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
activeServer, err := h.accountRepo.GetActiveServer(userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var activeServerID *uuid.UUID
|
||||
if activeServer != nil {
|
||||
activeServerID = &activeServer.ID
|
||||
}
|
||||
|
||||
response := make([]ServerShortDTO, 0, len(servers))
|
||||
for _, server := range servers {
|
||||
role, err := h.accountRepo.GetUserRole(userID, server.ID)
|
||||
if err != nil {
|
||||
role = account.RoleOperator
|
||||
}
|
||||
|
||||
response = append(response, ServerShortDTO{
|
||||
ID: server.ID.String(),
|
||||
Name: server.Name,
|
||||
Role: string(role),
|
||||
IsActive: activeServerID != nil && server.ID == *activeServerID,
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// SwitchActiveServerRequest - запрос на переключение активного сервера
|
||||
type SwitchActiveServerRequest struct {
|
||||
ServerID string `json:"server_id" binding:"required"`
|
||||
}
|
||||
|
||||
// SwitchActiveServer переключает активный сервер пользователя
|
||||
func (h *SettingsHandler) SwitchActiveServer(c *gin.Context) {
|
||||
userID := c.MustGet("userID").(uuid.UUID)
|
||||
|
||||
var req SwitchActiveServerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
serverID, err := uuid.Parse(req.ServerID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid server_id format"})
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем, что сервер доступен пользователю
|
||||
servers, err := h.accountRepo.GetAllAvailableServers(userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
var serverExists bool
|
||||
for _, s := range servers {
|
||||
if s.ID == serverID {
|
||||
serverExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !serverExists {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "server not found or not accessible"})
|
||||
return
|
||||
}
|
||||
|
||||
// Переключаем активный сервер
|
||||
if err := h.accountRepo.SetActiveServer(userID, serverID); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Сбрасываем кэш RMS клиента
|
||||
if h.rmsFactory != nil {
|
||||
h.rmsFactory.ClearCacheForUser(userID)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"status": "active_server_changed"})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user