From 0fa6de12eeddb75f55c900da9c379c163f36c6ec Mon Sep 17 00:00:00 2001 From: Rodrigo Martins Date: Wed, 1 Jan 2025 22:44:05 -0300 Subject: [PATCH] Estiliza pagina de upload externo - responsiva (novo47) --- config.php | 36 ++++++++ delete_document.php | 36 ++++++++ docs.sql | 18 ++++ document_detector.py | 100 ++++++++++++++++++++++ document_history.php | 85 +++++++++++++++++++ editor.php | 119 ++++++++++++++++++++++++++ index.php | 80 +++++++++++++----- list.php | 133 +++++++++++++++++++++++++++++ menu.php | 9 +- process.php | 91 ++++++++++++++++++++ style.css | 47 +++++++++++ upload.php | 195 +++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 925 insertions(+), 24 deletions(-) create mode 100644 config.php create mode 100644 delete_document.php create mode 100644 docs.sql create mode 100644 document_detector.py create mode 100644 document_history.php create mode 100644 editor.php create mode 100644 list.php create mode 100644 process.php create mode 100644 upload.php diff --git a/config.php b/config.php new file mode 100644 index 0000000..70fdeab --- /dev/null +++ b/config.php @@ -0,0 +1,36 @@ +connect_error) { + die("Falha na conexão: " . $conn->connect_error); +} + +// Configurar charset +$conn->set_charset("utf8mb4"); + +// Configurar timezone +date_default_timezone_set('America/Sao_Paulo'); + +// Função para limpar input +function clean_input($data) { + global $conn; + $data = trim($data); + $data = stripslashes($data); + $data = htmlspecialchars($data); + return $conn->real_escape_string($data); +} + +// Função para verificar se é uma requisição AJAX +function is_ajax_request() { + return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && + strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; +} +?> diff --git a/delete_document.php b/delete_document.php new file mode 100644 index 0000000..9a36ac1 --- /dev/null +++ b/delete_document.php @@ -0,0 +1,36 @@ +prepare($sql); + $stmt->bind_param("i", $doc_id); + $stmt->execute(); + $result = $stmt->get_result(); + + if ($doc = $result->fetch_assoc()) { + // Deletar arquivo físico + if (file_exists($doc['arquivo'])) { + unlink($doc['arquivo']); + } + + // Deletar registro do banco + $sql = "DELETE FROM documentos WHERE id = ?"; + $stmt = $conn->prepare($sql); + $stmt->bind_param("i", $doc_id); + + if ($stmt->execute()) { + header("Location: index.php?page=doc_list&client_id=" . $doc['client_id'] . "&status=deleted"); + } else { + die("Erro ao excluir documento: " . $stmt->error); + } + } else { + die("Documento não encontrado"); + } +} else { + die("ID do documento não fornecido"); +} +?> diff --git a/docs.sql b/docs.sql new file mode 100644 index 0000000..0c12e3a --- /dev/null +++ b/docs.sql @@ -0,0 +1,18 @@ +CREATE TABLE IF NOT EXISTS clientes ( + id INT AUTO_INCREMENT PRIMARY KEY, + nome VARCHAR(100) NOT NULL, + cpf VARCHAR(14) UNIQUE, + email VARCHAR(100), + telefone VARCHAR(20), + data_cadastro DATETIME DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS documentos ( + id INT AUTO_INCREMENT PRIMARY KEY, + client_id INT NOT NULL, + tipo VARCHAR(50) NOT NULL, + arquivo VARCHAR(255) NOT NULL, + data_upload DATETIME NOT NULL, + FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE, + INDEX idx_client_id (client_id) +) ENGINE=InnoDB; \ No newline at end of file diff --git a/document_detector.py b/document_detector.py new file mode 100644 index 0000000..a2135f4 --- /dev/null +++ b/document_detector.py @@ -0,0 +1,100 @@ +import cv2 +import numpy as np +import sys +import json +from pathlib import Path +import os +from PIL import Image + +def order_points(pts): + rect = np.zeros((4, 2), dtype="float32") + s = pts.sum(axis=1) + rect[0] = pts[np.argmin(s)] + rect[2] = pts[np.argmax(s)] + diff = np.diff(pts, axis=1) + rect[1] = pts[np.argmin(diff)] + rect[3] = pts[np.argmax(diff)] + return rect + +def process_document(image_path, doc_type, output_dir): + try: + # Carrega e verifica a imagem + image = cv2.imread(str(image_path)) + if image is None: + raise Exception("Não foi possível carregar a imagem") + + original = image.copy() + + # Pré-processamento + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + blurred = cv2.GaussianBlur(gray, (5, 5), 0) + edges = cv2.Canny(blurred, 50, 150) + + # Encontra contornos + contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + if not contours: + raise Exception("Nenhum contorno encontrado") + + # Ordena contornos por área + contours = sorted(contours, key=cv2.contourArea, reverse=True) + doc_corners = None + + # Procura o documento + for contour in contours: + peri = cv2.arcLength(contour, True) + approx = cv2.approxPolyDP(contour, 0.02 * peri, True) + if len(approx) == 4: + doc_corners = approx + break + + if doc_corners is None: + raise Exception("Documento não encontrado") + + # Processa cantos e aplica transformação + doc_corners = doc_corners.reshape(4, 2) + ordered_corners = order_points(doc_corners) + + (tl, tr, br, bl) = ordered_corners + widthA = np.linalg.norm(br - bl) + widthB = np.linalg.norm(tr - tl) + maxWidth = max(int(widthA), int(widthB)) + + heightA = np.linalg.norm(tr - br) + heightB = np.linalg.norm(tl - bl) + maxHeight = max(int(heightA), int(heightB)) + + dst = np.array([ + [0, 0], + [maxWidth - 1, 0], + [maxWidth - 1, maxHeight - 1], + [0, maxHeight - 1] + ], dtype="float32") + + # Aplica transformação perspectiva + matrix = cv2.getPerspectiveTransform(ordered_corners, dst) + warped = cv2.warpPerspective(original, matrix, (maxWidth, maxHeight)) + + # Salva resultado + output_path = os.path.join(output_dir, f"{doc_type}_{Path(image_path).name}") + cv2.imwrite(str(output_path), warped) + + return { + "success": True, + "message": "Processamento concluído com sucesso", + "width": maxWidth, + "height": maxHeight + } + + except Exception as e: + return { + "success": False, + "message": str(e) + } + +if __name__ == "__main__": + if len(sys.argv) != 4: + print(json.dumps({"success": False, "message": "Uso: python document_detector.py "})) + sys.exit(1) + + result = process_document(Path(sys.argv[1]), sys.argv[2], Path(sys.argv[3])) + print(json.dumps(result)) diff --git a/document_history.php b/document_history.php new file mode 100644 index 0000000..5681ca4 --- /dev/null +++ b/document_history.php @@ -0,0 +1,85 @@ +connect_error) { + die("Connection failed: " . $mysqli->connect_error); +} + +// Buscar histórico de documentos processados +$query = "SELECT pd.*, u.username FROM processed_documents pd + LEFT JOIN users u ON pd.user_id = u.id + ORDER BY pd.created_at DESC"; +$result = $mysqli->query($query); +?> + +
+

Histórico de Documentos Processados

+ + + + + + + + + + + + + fetch_assoc()): ?> + + + + + + + + + +
Data/HoraUsuárioDocumento OriginalDocumento ProcessadoAções
+ + Ver Original + + + + Ver Processado + + + +
+
+ + diff --git a/editor.php b/editor.php new file mode 100644 index 0000000..40bc872 --- /dev/null +++ b/editor.php @@ -0,0 +1,119 @@ + + + + Editor de Documentos + + + + +
+
+ +
+ +
+ + + + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + + + diff --git a/index.php b/index.php index 442e759..d13b91f 100644 --- a/index.php +++ b/index.php @@ -2,9 +2,10 @@ ob_start(); session_start(); +//require_once 'config.php'; // Verificar se o usuário está logado -if (!isset($_SESSION['user_id'])) { +if (!isset($_SESSION['user_id']) && !in_array($_GET['page'], ['login', 'logout'])) { header("Location: login.php"); exit(); } @@ -32,28 +33,61 @@ include 'top_menu.php'; Bem-vindo ao Sistema de Ferramentas"; + switch($page) { + case 'upload': + include 'prova/upload_prova.php'; + break; + case 'status': + include 'prova/status.php'; + break; + case 'list_files': + include 'prova/list_files.php'; + break; + case 'register_client': + include 'clientes/register_client.php'; + break; + case 'list_clients': + include 'clientes/list_clients.php'; + break; + case 'client_details': + if (isset($_GET['id'])) { + include 'clientes/client_details.php'; + } + break; + case 'edit_client': + if (isset($_GET['id'])) { + include 'clientes/edit_client.php'; + } + break; + case 'delete_client': + if (isset($_GET['id'])) { + include 'clientes/delete_client.php'; + } + break; + case 'edit_note': + if (isset($_POST['id'])) { + include 'clientes/edit_note.php'; + } + break; + case 'delete_note': + if (isset($_POST['id'])) { + include 'clientes/delete_note.php'; + } + break; + case 'doc_upload': + include 'upload.php'; + break; + case 'doc_list': + include 'list.php'; + break; + case 'delete_document': + if (isset($_GET['id'])) { + include 'delete_document.php'; + } + break; + default: + echo "

Bem-vindo ao Sistema de Ferramentas

"; + break; } } else { echo "

Bem-vindo ao Sistema de Ferramentas

"; diff --git a/list.php b/list.php new file mode 100644 index 0000000..5034573 --- /dev/null +++ b/list.php @@ -0,0 +1,133 @@ + + + + Documentos Processados + + + + +
+ \n"; + + if ($conn->connect_error) { + die("
Erro de conexão: " . $conn->connect_error . "
"); + } + + if (!isset($_GET['client_id'])) { + echo "

Selecione um cliente para ver seus documentos:

"; + $sql = "SELECT id, name FROM clients"; + echo "\n"; + + $result = $conn->query($sql); + + if ($result === false) { + echo "
Erro na query: " . $conn->error . "
"; + echo "\n"; + } else { + echo "\n"; + while ($row = $result->fetch_assoc()) { + echo "
"; + echo "
"; + echo "" . $row['name'] . ""; + echo "
"; + echo "
"; + echo "Ver documentos"; + echo "
"; + echo "
"; + } + } + } else { + $client_id = intval($_GET['client_id']); + echo "\n"; + + // Buscar documentos do cliente + $sql = "SELECT d.*, c.name as client_name + FROM documentos d + JOIN clients c ON d.client_id = c.id + WHERE d.client_id = ? + ORDER BY d.data_upload DESC"; + + echo "\n"; + + $stmt = $conn->prepare($sql); + if ($stmt === false) { + echo "
Erro ao preparar query: " . $conn->error . "
"; + } else { + $stmt->bind_param("i", $client_id); + $stmt->execute(); + $result = $stmt->get_result(); + + echo "\n"; + + if ($result->num_rows > 0) { + while ($doc = $result->fetch_assoc()) { + echo "
"; + echo "
"; + echo "Tipo: " . ucfirst($doc['tipo']) . "
"; + echo "Data: " . date("d/m/Y H:i", strtotime($doc['data_upload'])); + echo "
"; + echo "
"; + echo "Visualizar | "; + echo "Excluir"; + echo "
"; + echo "
"; + } + } else { + echo "

Nenhum documento encontrado para este cliente.

"; + } + } + } + ?> + + + +
+ +
+ +
+ + + + diff --git a/menu.php b/menu.php index afd199e..ecaf664 100644 --- a/menu.php +++ b/menu.php @@ -12,7 +12,7 @@ if (!isset($_SESSION['user_id'])) {
  • Autenticador de Provas Digitais @@ -24,6 +24,13 @@ if (!isset($_SESSION['user_id'])) {
  • Listagem de Clientes
  • +
  • + Processador de Documentos + +
  • diff --git a/process.php b/process.php new file mode 100644 index 0000000..bd67439 --- /dev/null +++ b/process.php @@ -0,0 +1,91 @@ +&1', + $python_script, + $original_path, + $doc_type, + $client_dir + ); + + // Log do comando + file_put_contents('python_debug.log', date('Y-m-d H:i:s') . "\nComando: " . $command . "\n", FILE_APPEND); + + // Executar comando + $output = []; + $return_var = 0; + exec($command, $output, $return_var); + + // Log da saída + file_put_contents('python_debug.log', "Saída: " . implode("\n", $output) . "\nCódigo: $return_var\n\n", FILE_APPEND); + + // Verificar resultado + $last_output = end($output); + $result = json_decode($last_output, true); + + if ($result && $result['success']) { + // Nome do arquivo processado + $processed_name = $doc_type . "_" . $original_name; + $processed_file = $client_dir . "/" . $processed_name; + + // Registrar no banco + $sql = "INSERT INTO documentos (client_id, tipo, arquivo, data_upload) VALUES (?, ?, ?, NOW())"; + $stmt = $conn->prepare($sql); + $stmt->bind_param("iss", $client_id, $doc_type, $processed_file); + + if (!$stmt->execute()) { + throw new Exception("Erro ao registrar documento: " . $stmt->error); + } + + header("Location: index.php?page=doc_list&client_id=" . $client_id . "&status=success"); + exit(); + } else { + throw new Exception("Erro no processamento: " . ($result['message'] ?? 'Erro desconhecido')); + } + + } catch (Exception $e) { + file_put_contents('error.log', date('Y-m-d H:i:s') . " - " . $e->getMessage() . "\n", FILE_APPEND); + die("Erro: " . $e->getMessage()); + } +} else { + die("Erro no upload: " . $_FILES["document"]["error"]); +} +?> diff --git a/style.css b/style.css index 4eb5acf..2723ee2 100644 --- a/style.css +++ b/style.css @@ -209,3 +209,50 @@ textarea { #search-button:hover { background-color: #0056b3; } + +/* Estilos para processamento de documentos */ +.upload-form { + max-width: 600px; + margin: 20px auto; + padding: 20px; + background: #f5f5f5; + border-radius: 5px; +} + +.result-preview { + margin-top: 30px; +} + +.image-comparison { + display: flex; + justify-content: space-around; + margin-top: 20px; + flex-wrap: wrap; +} + +.image-comparison img { + max-width: 45%; + height: auto; + margin: 10px; + border: 1px solid #ddd; + box-shadow: 0 0 5px rgba(0,0,0,0.2); +} + +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb; +} + +.alert-error { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +} diff --git a/upload.php b/upload.php new file mode 100644 index 0000000..ed807b6 --- /dev/null +++ b/upload.php @@ -0,0 +1,195 @@ + + + + + Upload de Documentos + + + + + +
    +

    Upload de Documentos

    + \n"; + require_once 'config.php'; + + if ($conn->connect_error) { + echo "
    Erro de conexão: " . $conn->connect_error . "
    "; + } else { + echo "\n"; + } + ?> +
    +

    +
    + +

    +

    +
    + +

    +

    +
    + +

    + +
    + +
    + + +
    + error; + } + ?> +
    +

    Ver documentos processados

    +
    + +
    +

    Resultado do Processamento:

    +
    +

    Documento Original:

    + Original +
    +
    +

    Documento Processado:

    + Processado +
    +
    + +
    + + + +