Instruções: Correções do Gerenciador de Dados
Este documento detalha a implementação e as correções para o componente Gerenciador de Dados, uma funcionalidade crítica do sistema Clio. Utilize as informações de arquitetura e convenções do arquivo Visão Geral de Engenharia de Rede como base para o desenvolvimento.
📋 Visão Geral da Funcionalidade
O Gerenciador de Dados (gerenciadordedados.vue) é a interface central para o registro e a verificação de integridade de documentos antes de entrarem no fluxo de catalogação de metadados.
Responsabilidades Principais:
- Configuração de Pastas: Permite ao usuário selecionar as pastas do Google Drive que serão monitoradas.
- Registro de Arquivos: Lista arquivos do Drive que ainda não foram registrados no sistema e permite sua inclusão na tabela
gerenciador_dados. - Verificação de Integridade: Executa uma série de verificações para encontrar inconsistências entre o Google Drive e o banco de dados local (ex: arquivos órfãos, registros ausentes).
- Visualização de Dados: Apresenta os dados já registrados com opções de filtro e busca.
🔧 Tecnologias e Arquivos Chave
| Camada | Tecnologia | Arquivo Principal | Propósito |
|---|---|---|---|
| Frontend | Vue.js 3, Pinia | iface-frontend-vuejs/src/components/gerenciadordedados/gerenciadordedados.vue | Interface do usuário para todas as operações de gerenciamento de dados. |
| Backend | Node.js, Express | node/backend/routes/gerenciadorDadosRoute.js | Fornece os endpoints RESTful para listar, registrar e verificar arquivos. |
🗄️ Estrutura de Dados e Mapeamento
O processo de registro depende da correlação entre a tabela de mapeamento do Drive (gerenciamento_googledrive) e a tabela de documentos do sistema (gerenciador_dados).
Relacionamento entre Tabelas
┌─────────────────────────────────────────────────────────────────────────┐
│ gerenciamento_googledrive │
│ (Cache/mapeamento de TODOS os arquivos no Google Drive) │
├─────────────────────────────────────────────────────────────────────────┤
│ id_drive ─────────────────────────────────────────────────────┐ │
│ (ID único do arquivo no Drive) │ │
│ │ │
│ parents ───────────────────────────────────────────────┐ │ │
│ (JSON array com IDs das pastas pai) │ │ │
└──────────────────────────────────────────────────────────│──────│────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ gerenciador_dados │
│ (Registros de documentos para catalogação) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ url_pdf ◄───── id_drive (se tipo_mimetype = 'application/pdf') │
│ │
│ url_jpg ◄───── id_drive (se tipo_mimetype LIKE 'image/%') │
│ │
│ google_drive_folder_id ◄───── parents[0] (ID da pasta pai) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Lógica de Mapeamento de Campos
Ao registrar um arquivo, os campos são preenchidos da seguinte forma:
| Tipo de Arquivo no Drive | Campo url_pdf | Campo url_jpg | Campo google_drive_folder_id |
|---|---|---|---|
PDF (application/pdf) | ✅ id_drive do arquivo | NULL | parents[0] (ID da pasta pai) |
Imagem (image/*) | NULL | ✅ id_drive do arquivo | parents[0] (ID da pasta pai) |
| Outros tipos (fallback) | ✅ id_drive do arquivo | NULL | parents[0] (ID da pasta pai) |
⚙️ Lógica do Backend (gerenciadorDadosRoute.js)
O backend orquestra o acesso ao banco de dados e aplica a lógica de negócio.
Padrão Crítico: Parser de Configuração INI
Problema: Senhas de banco de dados no arquivo .config.cfg podem conter o caractere #, que é interpretado como comentário por parsers padrão.
Solução: SEMPRE utilize a função parseConfigFile presente na rota para ler as configurações de conexão.
// Exemplo de uso obrigatório
async function getConnection() {
const configPath = path.join(/*...*/, '.config.cfg');
const config = parseConfigFile(configPath); // <-- USA A FUNÇÃO CUSTOMIZADA
// ... usa a config para conectar
}
Endpoints Principais
GET /api/gerenciador-dados/arquivos-pendentes
- Propósito: Lista arquivos do Google Drive que podem ser registrados.
- Lógica Chave:
- Busca arquivos da tabela
gerenciamento_googledrive. - Para cada arquivo, verifica se seu
id_drivejá existe na colunaurl_pdfouurl_jpgda tabelagerenciador_dados. - Retorna a lista com um campo booleano
ja_registrado. - Implementa paginação com
LIMITeOFFSETpara lidar com grandes volumes de dados.
- Busca arquivos da tabela
POST /api/gerenciador-dados/registrar
- Propósito: Registra um ou mais arquivos na tabela
gerenciador_dados. - Lógica Chave:
- Recebe um array de objetos de arquivo.
- Para cada arquivo, determina se é PDF ou Imagem para preencher
url_pdfouurl_jpgcorretamente. - Extrai o ID da pasta pai do campo
parents. - Executa uma verificação final de duplicatas antes de inserir.
- Insere o novo registro na tabela
gerenciador_dados.
GET /api/gerenciador-dados/check-integrity
- Propósito: Realiza verificações de consistência entre as tabelas.
- Lógica Chave:
- Modo Resumo: Se chamado sem parâmetros, retorna apenas a contagem de problemas em cada categoria.
- Modo Detalhado: Se chamado com
?problemType=<tipo>, retorna uma lista paginada dos registros que apresentam aquele problema específico.
- Verificações:
url_pdf_orfaos:url_pdfemgerenciador_dadosque não existe emgerenciamento_googledrive.url_jpg_orfaos:url_jpgemgerenciador_dadosque não existe emgerenciamento_googledrive.folder_id_orfaos:google_drive_folder_idemgerenciador_dadosque não existe emgerenciamento_googledrive.nao_catalogados: Arquivos emgerenciamento_googledriveque não estão emgerenciador_dados.
🖥️ Lógica do Frontend (gerenciadordedados.vue)
A interface reativa que consome os dados do backend.
Padrão Crítico: Reatividade com computed e ref
Utilize ref para estado reativo (filtros, página atual, dados brutos da API) e computed para dados derivados (listas filtradas, totais, estado de paginação).
Paginação e Filtragem Eficiente
Problema: A paginação era aplicada sobre a lista completa de dados, ignorando os filtros, o que causava inconsistências na UI.
Solução: Encadeie computed properties para garantir a ordem correta das operações.
// 1. Dados brutos da API
const arquivosParaRegistro = ref<ArquivoDrive[]>([]);
// 2. Aplica filtros sobre os dados brutos
const arquivosAposFiltros = computed(() => {
return arquivosParaRegistro.value.filter(arquivo => {
// ... lógica de filtro aqui ...
});
});
// 3. Aplica paginação sobre a lista JÁ FILTRADA
const arquivosPaginados = computed(() => {
const start = (currentPage.value - 1) * itemsPerPage.value;
const end = start + itemsPerPage.value;
return arquivosAposFiltros.value.slice(start, end);
});
// 4. A UI renderiza `arquivosPaginados`
// 5. Os totais e o número de páginas são calculados com base em `arquivosAposFiltros.length`
const totalPages = computed(() => Math.ceil(arquivosAposFiltros.value.length / itemsPerPage.value));
Reset de Página ao Mudar Filtros
Problema: O usuário podia ficar em uma página que não existe mais após aplicar um filtro (ex: estava na página 5, mas o resultado filtrado só tem 1 página).
Solução: Use watch para observar as variáveis de filtro e resetar a página atual para 1.
watch([filterColecao, filterTipo, searchQuery], () => {
currentPage.value = 1;
});
⚠️ Erros Comuns e Soluções
-
Erro de Build: "Object is possibly 'null' or 'undefined'"
- Causa: TypeScript detecta que uma variável pode ser nula. Comum ao acessar
document.getElementByIdou umrefde template antes de ser montado. - Solução: Use optional chaining (
?.) ou adicione uma verificação de nulidade (if (variavel) { ... }).
- Causa: TypeScript detecta que uma variável pode ser nula. Comum ao acessar
-
Erro de Template: Mismatched
<div>tags- Causa: Um
<div>extra ou ausente no template Vue. - Solução: Use a indentação do editor para inspecionar visualmente o aninhamento dos blocos e corrigir a estrutura.
- Causa: Um
-
Erro de Backend: "Unknown column 'collections' in 'field list'"
- Causa: A query SQL está tentando selecionar uma coluna
collectionsque não existe. - Solução: Corrija a query para usar
collections_json, que é o nome correto da coluna no banco de dados.
- Causa: A query SQL está tentando selecionar uma coluna
-
Inconsistência de Dados:
ja_registradovsjaRegistrado- Causa: O backend retorna o campo no formato
snake_casedo banco de dados, mas o frontend esperacamelCase. - Solução: Padronize a transformação no backend. Ao enviar dados para o frontend, converta os nomes dos campos para
camelCase.
- Causa: O backend retorna o campo no formato
-
Performance Lenta na Aba "Integridade"
- Causa: A API
/check-integrityestava buscando todos os registros detalhados de todos os problemas de uma só vez, causando timeouts com +25.000 registros. - Solução: Refatorar a API para o padrão Resumo/Detalhe, onde a chamada inicial busca apenas as contagens e chamadas subsequentes (e paginadas) buscam os detalhes de um problema específico.
- Causa: A API