adiciona views, templates, urls e documentos do elastic search
This commit is contained in:
310
diarios/templates/diarios/search_results.html
Normal file
310
diarios/templates/diarios/search_results.html
Normal file
@ -0,0 +1,310 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pt-BR">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% if query %}{{ query }} - {% endif %}Pesquisa de Documentos</title>
|
||||
<!-- Bootstrap 5 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Fonte personalizada -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||
<!-- Ícones do Bootstrap -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Roboto', Arial, sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
color: #202124;
|
||||
}
|
||||
.search-container {
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.main-container {
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.search-box {
|
||||
border-radius: 24px;
|
||||
border: 1px solid #dfe1e5;
|
||||
box-shadow: none;
|
||||
height: 44px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.search-box:focus {
|
||||
box-shadow: 0 1px 6px rgba(32,33,36,.28);
|
||||
border-color: rgba(223,225,229,0);
|
||||
}
|
||||
.search-button {
|
||||
border-radius: 24px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.result-item {
|
||||
padding: 20px 0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
.result-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.result-title {
|
||||
color: #1a0dab;
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.result-title a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.result-title a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.result-content {
|
||||
color: #4d5156;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
line-height: 1.58;
|
||||
}
|
||||
.result-meta {
|
||||
color: #70757a;
|
||||
font-size: 12px;
|
||||
}
|
||||
.suggestion {
|
||||
color: #1a0dab;
|
||||
text-decoration: none;
|
||||
}
|
||||
.suggestion:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
mark {
|
||||
background-color: #ffffc2;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.related-term {
|
||||
color: #70757a;
|
||||
font-size: 14px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.pagination-link {
|
||||
color: #1a0dab;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.pagination-link.active {
|
||||
color: #202124;
|
||||
font-weight: bold;
|
||||
}
|
||||
.pagination-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.search-stats {
|
||||
color: #70757a;
|
||||
font-size: 14px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.header {
|
||||
padding: 20px 0;
|
||||
background-color: white;
|
||||
border-bottom: 1px solid #dfe1e5;
|
||||
}
|
||||
.badge-exact-match {
|
||||
background-color: #e8f0fe;
|
||||
color: #1a73e8;
|
||||
border: 1px solid #d2e3fc;
|
||||
font-weight: normal;
|
||||
}
|
||||
.search-tip {
|
||||
font-size: 13px;
|
||||
color: #70757a;
|
||||
margin-top: 5px;
|
||||
}
|
||||
</style>
|
||||
<div class="position-relative">
|
||||
<input type="text" name="q" class="form-control search-box"
|
||||
id="searchInput" autocomplete="off">
|
||||
<div id="suggestionsBox" class="position-absolute w-100 bg-white shadow"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// JavaScript para sugestões em tempo real
|
||||
document.getElementById('searchInput').addEventListener('input', function(e) {
|
||||
const query = e.target.value;
|
||||
if(query.length > 2) {
|
||||
fetch(`/diarios/spellcheck/?q=${encodeURIComponent(query)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const suggestionsBox = document.getElementById('suggestionsBox');
|
||||
suggestionsBox.innerHTML = data.suggestions.map(sug =>
|
||||
`<div class="suggestion-item p-2 border-bottom cursor-pointer">
|
||||
${sug}
|
||||
</div>`
|
||||
).join('');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Clique na sugestão
|
||||
document.getElementById('suggestionsBox').addEventListener('click', function(e) {
|
||||
if(e.target.classList.contains('suggestion-item')) {
|
||||
document.getElementById('searchInput').value = e.target.textContent;
|
||||
this.innerHTML = '';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Cabeçalho com barra de pesquisa -->
|
||||
<header class="header">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<a href="/" class="text-decoration-none">
|
||||
<h3 class="mb-0 text-primary"><i class="bi bi-search"></i> BuscaDocs</h3>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<form action="{% url 'search_view' %}" method="get" class="d-flex">
|
||||
<input type="text" name="q" class="form-control search-box" value="{{ query }}" placeholder="Pesquisar documentos..." aria-label="Pesquisar">
|
||||
<button class="btn btn-primary search-button" type="submit"><i class="bi bi-search"></i></button>
|
||||
</form>
|
||||
<div class="search-tip">
|
||||
Use aspas duplas para buscar frases exatas, ex: "documento oficial"
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container py-4 main-container">
|
||||
{% if query %}
|
||||
<!-- Estatísticas da busca -->
|
||||
<div class="search-stats">
|
||||
{% if total_hits > 0 %}
|
||||
<p>Cerca de {{ total_hits }} resultados encontrados para "{{ query }}"</p>
|
||||
{% else %}
|
||||
<p>Nenhum resultado encontrado para "{{ query }}"</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Correção ortográfica -->
|
||||
{% if spelling_correction %}
|
||||
<div class="mb-4">
|
||||
<p>Você quis dizer: <a href="?q={{ spelling_correction|urlencode }}" class="suggestion">{{ spelling_correction }}</a>?</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Sugestões de termos -->
|
||||
{% if suggestions %}
|
||||
<div class="mb-4">
|
||||
<p>Talvez você esteja procurando por:
|
||||
{% for suggestion in suggestions %}
|
||||
<a href="?q={{ suggestion|urlencode }}" class="suggestion me-2">{{ suggestion }}</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Resultados da busca -->
|
||||
{% if results %}
|
||||
<div class="results-container">
|
||||
{% for result in results %}
|
||||
<div class="result-item">
|
||||
<div class="d-flex gap-2 mb-2">
|
||||
{% if result.is_exact_match %}
|
||||
<span class="badge badge-exact-match">Correspondência exata</span>
|
||||
{% endif %}
|
||||
{% if result.is_related %}
|
||||
<span class="badge bg-secondary">Termo relacionado</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<h5 class="result-title">
|
||||
<a href="#">{{ result.highlighted_title|safe }}</a>
|
||||
</h5>
|
||||
<div class="result-content">{{ result.highlighted_content|safe }}</div>
|
||||
<div class="result-meta">
|
||||
<i class="bi bi-calendar-date"></i> {{ result.uploaded_at|date:"d/m/Y" }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Paginação -->
|
||||
{% if total_pages > 1 %}
|
||||
<nav aria-label="Paginação de resultados" class="my-4">
|
||||
<div class="d-flex justify-content-center">
|
||||
{% if page > 1 %}
|
||||
<a href="?q={{ query|urlencode }}&page={{ page|add:'-1' }}" class="pagination-link">
|
||||
<i class="bi bi-chevron-left"></i> Anterior
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% for p in page_range %}
|
||||
<a href="?q={{ query|urlencode }}&page={{ p }}" class="pagination-link {% if p == page %}active{% endif %}">
|
||||
{{ p }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
||||
{% if page < total_pages %}
|
||||
<a href="?q={{ query|urlencode }}&page={{ page|add:'1' }}" class="pagination-link">
|
||||
Próxima <i class="bi bi-chevron-right"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="alert alert-info" role="alert">
|
||||
<i class="bi bi-info-circle-fill me-2"></i>
|
||||
Nenhum documento corresponde aos termos de pesquisa. Tente usar palavras-chave diferentes ou mais gerais.
|
||||
{% if has_exact_phrases %}
|
||||
<p class="mt-2 mb-0">Você pesquisou por frases exatas. Tente remover as aspas para uma busca mais ampla.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<!-- Página inicial de pesquisa -->
|
||||
<div class="text-center py-5">
|
||||
<h1 class="display-4 mb-4 text-primary"><i class="bi bi-search"></i> BuscaDocs</h1>
|
||||
<div class="search-container mb-4">
|
||||
<form action="{% url 'search_view' %}" method="get">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" name="q" class="form-control search-box py-3" placeholder="Pesquisar documentos..." aria-label="Pesquisar">
|
||||
<button class="btn btn-primary search-button px-4" type="submit">
|
||||
<i class="bi bi-search"></i> Pesquisar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<p class="text-muted">Pesquise em nossa biblioteca de documentos digitalizados</p>
|
||||
<div class="mt-3 text-start p-3 border rounded bg-light">
|
||||
<h5>Dicas de pesquisa:</h5>
|
||||
<ul class="mb-0">
|
||||
<li>Use <strong>aspas duplas</strong> para buscar frases exatas: <code>"documento oficial"</code></li>
|
||||
<li>Tente usar sinônimos se não encontrar resultados</li>
|
||||
<li>Seja específico para encontrar documentos relevantes</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="bg-light py-3 mt-5">
|
||||
<div class="container text-center">
|
||||
<p class="text-muted mb-0">© 2025 BuscaDocs - Sistema de Pesquisa de Documentos</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap JS Bundle with Popper -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<!-- Script para sugestões em tempo real (opcional) -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const searchInput = document.querySelector('input[name="q"]');
|
||||
searchInput.focus();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user