versão 13h12 12/02
This commit is contained in:
parent
beead0b6b2
commit
d36d7f76d3
56
src/App.vue
56
src/App.vue
@ -85,7 +85,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
|
|
||||||
<!-- Top Bar -->
|
<!-- Updated Top Bar -->
|
||||||
<v-app-bar
|
<v-app-bar
|
||||||
elevation="1"
|
elevation="1"
|
||||||
height="64"
|
height="64"
|
||||||
@ -93,25 +93,15 @@
|
|||||||
>
|
>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
|
||||||
<!-- Top Bar Actions -->
|
<!-- Admin User Profile -->
|
||||||
<v-btn
|
<div class="d-flex align-center mr-2">
|
||||||
variant="text"
|
<v-avatar color="primary" size="32" class="mr-2">
|
||||||
icon="mdi-bell"
|
<v-icon>mdi-account</v-icon>
|
||||||
class="mr-2"
|
</v-avatar>
|
||||||
>
|
<span class="text-subtitle-2 font-weight-medium">Admin User</span>
|
||||||
<v-badge
|
</div>
|
||||||
color="error"
|
|
||||||
content="3"
|
|
||||||
dot
|
|
||||||
></v-badge>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
variant="text"
|
|
||||||
icon="mdi-cog"
|
|
||||||
class="mr-2"
|
|
||||||
></v-btn>
|
|
||||||
|
|
||||||
|
<!-- Logout Button -->
|
||||||
<v-btn
|
<v-btn
|
||||||
color="error"
|
color="error"
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
@ -160,13 +150,6 @@ export default {
|
|||||||
label: 'Dashboard',
|
label: 'Dashboard',
|
||||||
badge: { text: 'Novo', color: 'success' }
|
badge: { text: 'Novo', color: 'success' }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'monitoring',
|
|
||||||
route: { name: 'monitoring' },
|
|
||||||
icon: 'mdi-cctv',
|
|
||||||
label: 'Monitoramento',
|
|
||||||
badge: { text: '12', color: 'info' }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'analytics',
|
name: 'analytics',
|
||||||
route: { name: 'analytics' },
|
route: { name: 'analytics' },
|
||||||
@ -179,13 +162,6 @@ export default {
|
|||||||
icon: 'mdi-file-chart',
|
icon: 'mdi-file-chart',
|
||||||
label: 'Relatórios'
|
label: 'Relatórios'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'alerts',
|
|
||||||
route: { name: 'alerts' },
|
|
||||||
icon: 'mdi-bell-ring',
|
|
||||||
label: 'Alertas',
|
|
||||||
badge: { text: '3', color: 'error' }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'testing',
|
name: 'testing',
|
||||||
route: { name: 'testing' },
|
route: { name: 'testing' },
|
||||||
@ -199,24 +175,12 @@ export default {
|
|||||||
icon: 'mdi-file-document-plus',
|
icon: 'mdi-file-document-plus',
|
||||||
label: 'Registro'
|
label: 'Registro'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'cameras',
|
|
||||||
route: { name: 'cameras' },
|
|
||||||
icon: 'mdi-camera',
|
|
||||||
label: 'Câmeras'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'users',
|
name: 'users',
|
||||||
route: { name: 'users' },
|
route: { name: 'users' },
|
||||||
icon: 'mdi-account-group',
|
icon: 'mdi-account-group',
|
||||||
label: 'Usuários'
|
label: 'Usuários'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'settings',
|
|
||||||
route: { name: 'settings' },
|
|
||||||
icon: 'mdi-cog',
|
|
||||||
label: 'Configurações'
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -235,7 +199,7 @@ export default {
|
|||||||
async handleLogout() {
|
async handleLogout() {
|
||||||
try {
|
try {
|
||||||
await this.logout();
|
await this.logout();
|
||||||
this.$router.push('/login');
|
this.$router.push({ name: 'login' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao fazer logout:', error);
|
console.error('Erro ao fazer logout:', error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,16 +3,15 @@ import HomeView from '@/views/HomeView.vue';
|
|||||||
import DashboardView from '@/views/DashboardView.vue';
|
import DashboardView from '@/views/DashboardView.vue';
|
||||||
import UsersView from '@/views/UsersView.vue';
|
import UsersView from '@/views/UsersView.vue';
|
||||||
import ReportsView from '@/views/ReportsView.vue';
|
import ReportsView from '@/views/ReportsView.vue';
|
||||||
import TestingView from '@/views/TestingView.vue';
|
import TestingView from '@/views/testingView.vue';
|
||||||
import ApiTester from '@/components/testing/ApiTester.vue';
|
|
||||||
import LoginView from '@/views/LoginView.vue';
|
import LoginView from '@/views/LoginView.vue';
|
||||||
import ForgotPassword from '@/views/ForgotPassword.vue';
|
import ForgotPassword from '@/views/ForgotPassword.vue';
|
||||||
import RegisterView from '@/views/RegisterView.vue';
|
import RegisterView from '@/views/RegisterView.vue';
|
||||||
import TrainingView from '@/views/TrainingView.vue';
|
|
||||||
import SSOView from '@/views/SSOView.vue';
|
import SSOView from '@/views/SSOView.vue';
|
||||||
import UserProfileView from '@/views/UserProfileView.vue';
|
import UserProfileView from '@/views/UserProfileView.vue';
|
||||||
import EditUserView from '@/views/EditUserView.vue';
|
import EditUserView from '@/views/EditUserView.vue';
|
||||||
import RegisterUserCamView from '@/views/RegisterUserCamView.vue';
|
import RegisterUserCamView from '@/views/RegisteruserCamView.vue';
|
||||||
|
import AboutView from '@/views/AboutView.vue';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -25,28 +24,19 @@ const routes = [
|
|||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: LoginView,
|
component: LoginView,
|
||||||
meta: {
|
meta: { public: true, requiresAuth: false }
|
||||||
public: true,
|
|
||||||
requiresAuth: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/forgot-password',
|
path: '/forgot-password',
|
||||||
name: 'forgot-password',
|
name: 'forgot-password',
|
||||||
component: ForgotPassword,
|
component: ForgotPassword,
|
||||||
meta: {
|
meta: { public: true, requiresAuth: false }
|
||||||
public: true,
|
|
||||||
requiresAuth: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/register',
|
path: '/register',
|
||||||
name: 'register',
|
name: 'register',
|
||||||
component: RegisterView,
|
component: RegisterView,
|
||||||
meta: {
|
meta: { public: true, requiresAuth: false }
|
||||||
public: true,
|
|
||||||
requiresAuth: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
@ -84,26 +74,11 @@ const routes = [
|
|||||||
component: TestingView,
|
component: TestingView,
|
||||||
meta: { requiresAuth: true }
|
meta: { requiresAuth: true }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/training',
|
|
||||||
name: 'training',
|
|
||||||
component: TrainingView,
|
|
||||||
meta: { requiresAuth: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/api-test',
|
|
||||||
name: 'api-test',
|
|
||||||
component: ApiTester,
|
|
||||||
meta: { requiresAuth: true }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/sso',
|
path: '/sso',
|
||||||
name: 'sso',
|
name: 'sso',
|
||||||
component: SSOView,
|
component: SSOView,
|
||||||
meta: {
|
meta: { public: true, requiresAuth: false }
|
||||||
public: true,
|
|
||||||
requiresAuth: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/register-user-cam',
|
path: '/register-user-cam',
|
||||||
@ -111,6 +86,12 @@ const routes = [
|
|||||||
component: RegisterUserCamView,
|
component: RegisterUserCamView,
|
||||||
meta: { requiresAuth: true }
|
meta: { requiresAuth: true }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/about',
|
||||||
|
name: 'about',
|
||||||
|
component: AboutView,
|
||||||
|
meta: { requiresAuth: false }
|
||||||
|
},
|
||||||
// Catch-all route for unmatched paths
|
// Catch-all route for unmatched paths
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
|
|||||||
@ -1,239 +0,0 @@
|
|||||||
<template>
|
|
||||||
<app-layout>
|
|
||||||
<v-container>
|
|
||||||
<v-card>
|
|
||||||
<v-tabs v-model="activeTab">
|
|
||||||
<v-tab>Pesquisar</v-tab>
|
|
||||||
<v-tab>Treino</v-tab>
|
|
||||||
<v-tab>Lista de Nomes</v-tab>
|
|
||||||
</v-tabs>
|
|
||||||
|
|
||||||
<v-card-text>
|
|
||||||
|
|
||||||
<!-- Pesquisar Tab -->
|
|
||||||
<v-form v-if="activeTab === 0" @submit.prevent="searchCameraModels">
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12" md="6">
|
|
||||||
<v-text-field v-model="searchCriteria.name" label="Nome do Modelo"></v-text-field>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" md="6">
|
|
||||||
<v-text-field v-model="searchCriteria.id" label="ID"></v-text-field>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" md="6">
|
|
||||||
<v-select v-model="searchCriteria.status" :items="['Ativo', 'Inativo']" label="Status"></v-select>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" md="6">
|
|
||||||
<v-select v-model="searchCriteria.order" :items="['A-Z', 'Z-A']" label="Ordenar"></v-select>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-btn type="submit" color="primary">Pesquisar</v-btn>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-form>
|
|
||||||
|
|
||||||
<v-list v-if="searchResults.length">
|
|
||||||
<v-list-item-group>
|
|
||||||
<v-list-item v-for="(camera, index) in searchResults" :key="index">
|
|
||||||
<v-list-item-content>
|
|
||||||
<v-list-item-title>{{ camera.name }}</v-list-item-title>
|
|
||||||
<v-list-item-subtitle>{{ camera.id }}</v-list-item-subtitle>
|
|
||||||
<v-list-item-subtitle>{{ camera.registrationDate }}</v-list-item-subtitle>
|
|
||||||
<v-list-item-subtitle>{{ camera.isActive ? 'Ativo' : 'Inativo' }}</v-list-item-subtitle>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list-item-group>
|
|
||||||
</v-list>
|
|
||||||
|
|
||||||
<!-- Treino Tab -->
|
|
||||||
<v-row v-if="activeTab === 1">
|
|
||||||
<v-col>
|
|
||||||
<v-card outlined>
|
|
||||||
<v-card-title>Treinamento de Modelo de Câmera</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<v-row>
|
|
||||||
<v-col cols="12" md="8">
|
|
||||||
<v-select
|
|
||||||
:items="untrainedCameras"
|
|
||||||
v-model="selectedCameraForTraining"
|
|
||||||
label="Selecionar Câmera"
|
|
||||||
item-text="name"
|
|
||||||
return-object
|
|
||||||
></v-select>
|
|
||||||
</v-col>
|
|
||||||
<v-col cols="12" md="4" class="d-flex">
|
|
||||||
<v-btn
|
|
||||||
color="primary"
|
|
||||||
class="mr-2"
|
|
||||||
@click="startTraining"
|
|
||||||
:disabled="!selectedCameraForTraining"
|
|
||||||
>
|
|
||||||
Iniciar Treinamento
|
|
||||||
</v-btn>
|
|
||||||
<v-btn
|
|
||||||
color="success"
|
|
||||||
@click="integrateModel"
|
|
||||||
:disabled="!trainingComplete"
|
|
||||||
>
|
|
||||||
Integrar
|
|
||||||
</v-btn>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
<v-progress-linear
|
|
||||||
v-if="isTraining"
|
|
||||||
:value="trainingProgress"
|
|
||||||
color="primary"
|
|
||||||
height="20"
|
|
||||||
></v-progress-linear>
|
|
||||||
<v-row v-if="trainingMessage">
|
|
||||||
<v-col>{{ trainingMessage }}</v-col>
|
|
||||||
</v-row>
|
|
||||||
<v-row v-if="trainingComplete">
|
|
||||||
<v-col>
|
|
||||||
<v-card>
|
|
||||||
<v-card-title>Informações da Câmera</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<p><strong>Nome:</strong> {{ selectedCameraForTraining.name }}</p>
|
|
||||||
<p><strong>Status do Treinamento:</strong> Concluído</p>
|
|
||||||
<p><strong>Status da Integração:</strong> {{ integrationStatus }}</p>
|
|
||||||
<p><strong>Tempo de Treinamento:</strong> 5 minutos</p>
|
|
||||||
<p><strong>Tempo de Integração:</strong> 3 minutos</p>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<!-- Lista de Nomes Tab -->
|
|
||||||
<v-row v-if="activeTab === 2" class="mt-4">
|
|
||||||
<v-col md="6" sm="12">
|
|
||||||
<v-card outlined>
|
|
||||||
<v-card-title class="subtitle-1">Rostos Identificados</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<v-select v-model="selectedFaceStatus" :items="['Associado', 'Não Associado']" label="Filtrar Rostos"></v-select>
|
|
||||||
<v-list>
|
|
||||||
<v-list-item v-for="(face, index) in filteredFaces" :key="index">
|
|
||||||
<v-list-item-avatar>
|
|
||||||
<v-icon large>mdi-account-circle</v-icon>
|
|
||||||
</v-list-item-avatar>
|
|
||||||
<v-list-item-content>
|
|
||||||
<v-list-item-title>{{ face.name }}</v-list-item-title>
|
|
||||||
<v-list-item-subtitle>{{ face.isActive ? 'Associado' : 'Não Associado' }}</v-list-item-subtitle>
|
|
||||||
<v-btn v-if="!face.isActive" @click="editFaceName(face)">Associar</v-btn>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-container>
|
|
||||||
</app-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
activeTab: 0,
|
|
||||||
searchCriteria: {
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
status: '',
|
|
||||||
order: ''
|
|
||||||
},
|
|
||||||
selectedCameraForTraining: null,
|
|
||||||
isTraining: false,
|
|
||||||
trainingComplete: false,
|
|
||||||
trainingProgress: 0,
|
|
||||||
trainingMessage: '',
|
|
||||||
untrainedCameras: [
|
|
||||||
{ id: 'CAM003', name: 'Câmera Estacionamento', brand: 'Dahua' }
|
|
||||||
],
|
|
||||||
cameras: [
|
|
||||||
{ id: 'CAM001', name: 'Câmera Principal', description: 'Câmera frontal do prédio', isActive: true, registrationDate: '2025-02-03T 08:30', isTrained: true },
|
|
||||||
{ id: 'CAM002', name: 'Câmera Corredor', description: 'Câmera do corredor principal', isActive: false, registrationDate: '2025-01-28T 14:00', isTrained: false }
|
|
||||||
],
|
|
||||||
searchResults: [],
|
|
||||||
selectedFaceStatus: 'Associado',
|
|
||||||
identifiedFaces: [
|
|
||||||
{ id: 'USER001', name: 'João Silva', isActive: true },
|
|
||||||
{ id: 'USER002', name: 'Maria Souza', isActive: true }
|
|
||||||
],
|
|
||||||
unidentifiedFaces: [
|
|
||||||
{ selectedUser: null, name: 'Desconhecido' },
|
|
||||||
{ selectedUser: null, name: 'Desconhecido' }
|
|
||||||
],
|
|
||||||
registeredUsers: ['João Silva', 'Maria Souza', 'Pedro Santos', 'Ana Oliveira'],
|
|
||||||
integrationStatus: 'Pendente',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
searchCameraModels() {
|
|
||||||
this.searchResults = this.cameras.filter(camera =>
|
|
||||||
(camera.id.includes(this.searchCriteria.id) || camera.name.includes(this.searchCriteria.name)) &&
|
|
||||||
(!this.searchCriteria.status || (this.searchCriteria.status === 'Ativo' && camera.isActive) || (this.searchCriteria.status === 'Inativo' && !camera.isActive))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.searchCriteria.order === 'A-Z') {
|
|
||||||
this.searchResults.sort((a, b) => a.name.localeCompare(b.name));
|
|
||||||
} else if (this.searchCriteria.order === 'Z-A') {
|
|
||||||
this.searchResults.sort((a, b) => b.name.localeCompare(a.name));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
startTraining() {
|
|
||||||
if (this.selectedCameraForTraining) {
|
|
||||||
this.isTraining = true;
|
|
||||||
this.trainingProgress = 0;
|
|
||||||
this.trainingMessage = 'Iniciando treinamento...';
|
|
||||||
|
|
||||||
const simulateTraining = setInterval(() => {
|
|
||||||
this.trainingProgress += 20;
|
|
||||||
|
|
||||||
switch(this.trainingProgress) {
|
|
||||||
case 20:
|
|
||||||
this.trainingMessage = 'Carregando modelos de reconhecimento...';
|
|
||||||
break;
|
|
||||||
case 40:
|
|
||||||
this.trainingMessage = 'Processando imagens de treinamento...';
|
|
||||||
break;
|
|
||||||
case 60:
|
|
||||||
this.trainingMessage = 'Ajustando parâmetros do modelo...';
|
|
||||||
break;
|
|
||||||
case 80:
|
|
||||||
this.trainingMessage = 'Finalizando treinamento...';
|
|
||||||
break;
|
|
||||||
case 100:
|
|
||||||
this.trainingMessage = 'Treinamento concluído!';
|
|
||||||
this.trainingComplete = true;
|
|
||||||
clearInterval(simulateTraining);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
integrateModel() {
|
|
||||||
this.integrationStatus = 'Em andamento...';
|
|
||||||
setTimeout(() => {
|
|
||||||
this.integrationStatus = 'Concluído';
|
|
||||||
}, 3000);
|
|
||||||
},
|
|
||||||
editFaceName(face) {
|
|
||||||
console.log('Editando rosto:', face);
|
|
||||||
face.isActive = true;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
filteredFaces() {
|
|
||||||
return this.selectedFaceStatus === 'Associado' ?
|
|
||||||
this.identifiedFaces.filter(face => face.isActive) :
|
|
||||||
this.unidentifiedFaces.filter(face => !face.isActive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
Loading…
Reference in New Issue
Block a user