versão 03/02 ás 15h43
This commit is contained in:
parent
712a87b696
commit
81485a7a67
218
src/App.vue
218
src/App.vue
@ -1,104 +1,168 @@
|
|||||||
<!-- App.vue -->
|
|
||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<v-app-bar app color="primary" dark elevation="2">
|
<!-- Menu Lateral com Opção de Recolher -->
|
||||||
<div class="d-flex align-center">
|
<v-navigation-drawer
|
||||||
<img
|
app
|
||||||
alt="Logo"
|
:width="drawerWidth"
|
||||||
class="logo"
|
:permanent="!canCollapse"
|
||||||
src="@/assets/logo.o.png"
|
:mobile-breakpoint="breakpoint"
|
||||||
width="50"
|
color="blue-darken-4"
|
||||||
height="50"
|
class="sidebar-navigation"
|
||||||
/>
|
>
|
||||||
<span class="ml-3 text-h6">TARS</span>
|
<div class="d-flex justify-end pa-2" v-if="canCollapse">
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
@click="toggleDrawer"
|
||||||
|
color="white"
|
||||||
|
class="collapse-button"
|
||||||
|
>
|
||||||
|
<v-icon>{{ isCollapsed ? 'mdi-menu' : 'mdi-chevron-left' }}</v-icon>
|
||||||
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-spacer></v-spacer>
|
<v-list>
|
||||||
|
<!-- Ícone + Nome TARS -->
|
||||||
|
<v-list-item class="d-flex align-center">
|
||||||
|
<v-list-item-avatar class="mr-3">
|
||||||
|
<v-icon color="white">mdi-robot</v-icon>
|
||||||
|
</v-list-item-avatar>
|
||||||
|
<v-list-item-title class="text-h6 text-white font-weight-bold" v-if="!isCollapsed">
|
||||||
|
TARS
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
<v-btn
|
<v-divider class="mb-4"></v-divider>
|
||||||
to="/"
|
|
||||||
text
|
|
||||||
class="mx-2"
|
|
||||||
>
|
|
||||||
Inicio
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn
|
|
||||||
to="/about"
|
|
||||||
text
|
|
||||||
class="mx-2"
|
|
||||||
>
|
|
||||||
Sobre
|
|
||||||
</v-btn>
|
|
||||||
</v-app-bar>
|
|
||||||
|
|
||||||
<v-main class="bg-grey-lighten-4">
|
<!-- Itens do Menu -->
|
||||||
<v-container fluid>
|
<v-list-item link :to="{ name: 'home' }" class="d-flex align-center">
|
||||||
<router-view />
|
<v-list-item-icon class="mr-3">
|
||||||
</v-container>
|
<v-icon color="white">mdi-home</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Home</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'user-profile' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-account</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Perfil</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'dashboard' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-view-dashboard</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Dashboard</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'reports' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-chart-bar</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Relatórios</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'training' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-brain</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Treinamento</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'users' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-account-group</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Usuários</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'testing' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-flask</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Testes</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item @click="logout" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-logout</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Sair</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item link :to="{ name: 'settings' }" class="d-flex align-center">
|
||||||
|
<v-list-item-icon class="mr-3">
|
||||||
|
<v-icon color="white">mdi-cog</v-icon>
|
||||||
|
</v-list-item-icon>
|
||||||
|
<v-list-item-title class="text-white" v-if="!isCollapsed">Configurações</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-navigation-drawer>
|
||||||
|
|
||||||
|
<!-- Conteúdo Principal -->
|
||||||
|
<v-main>
|
||||||
|
<router-view />
|
||||||
</v-main>
|
</v-main>
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
data() {
|
||||||
|
return {
|
||||||
data: () => ({
|
isCollapsed: false,
|
||||||
//
|
canCollapse: true,
|
||||||
}),
|
breakpoint: 600
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
drawerWidth() {
|
||||||
|
return this.isCollapsed ? 64 : 240
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleDrawer() {
|
||||||
|
this.isCollapsed = !this.isCollapsed
|
||||||
|
},
|
||||||
|
logout() {
|
||||||
|
// Lógica de logout
|
||||||
|
// Por exemplo:
|
||||||
|
// this.$store.dispatch('logout')
|
||||||
|
// this.$router.push('/login')
|
||||||
|
console.log('Logout')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
.logo {
|
.sidebar-navigation {
|
||||||
display: inline-block;
|
transition: width 0.3s ease;
|
||||||
transition: transform 0.3s ease;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo:hover {
|
.v-navigation-drawer {
|
||||||
transform: scale(1.05);
|
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
.v-list-item {
|
||||||
.logo {
|
transition: background-color 0.2s ease;
|
||||||
width: 40px;
|
border-radius: 8px;
|
||||||
height: 40px;
|
margin: 4px 8px;
|
||||||
}
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Estilos globais */
|
.v-list-item:hover {
|
||||||
:root {
|
background-color: rgba(255, 255, 255, 0.15);
|
||||||
--app-background: #f5f5f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
.v-list-item-title {
|
||||||
margin: 0;
|
font-size: 16px;
|
||||||
padding: 0;
|
opacity: 1;
|
||||||
height: 100%;
|
transition: opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
.collapse-button {
|
||||||
font-family: 'Roboto', sans-serif;
|
margin-bottom: 8px;
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Correções para o Vuetify */
|
|
||||||
.v-application {
|
|
||||||
min-height: 100vh;
|
|
||||||
background-color: var(--app-background) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-main {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Correção para o container em telas menores */
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.v-container {
|
|
||||||
padding: 12px !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -10,7 +10,6 @@ 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 TrainingView from '@/views/TrainingView.vue';
|
||||||
import SSOView from '@/views/SSOView.vue';
|
import SSOView from '@/views/SSOView.vue';
|
||||||
import AboutView from '@/views/AboutView.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'
|
||||||
|
|
||||||
@ -105,12 +104,6 @@ const routes = [
|
|||||||
requiresAuth: false
|
requiresAuth: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/about',
|
|
||||||
name: 'about',
|
|
||||||
component: AboutView,
|
|
||||||
meta: { requiresAuth: true }
|
|
||||||
},
|
|
||||||
// Catch-all route for unmatched paths
|
// Catch-all route for unmatched paths
|
||||||
{
|
{
|
||||||
path: '/:pathMatch(.*)*',
|
path: '/:pathMatch(.*)*',
|
||||||
|
|||||||
@ -49,6 +49,21 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
</v-form>
|
</v-form>
|
||||||
|
|
||||||
|
<!-- Câmera ID Tab -->
|
||||||
|
<v-row v-if="activeTab === 1">
|
||||||
|
<v-col cols="12" md="6" v-for="camera in cameras" :key="camera.id">
|
||||||
|
<v-card outlined>
|
||||||
|
<v-card-title>{{ camera.name }}</v-card-title>
|
||||||
|
<v-card-subtitle>{{ camera.id }}</v-card-subtitle>
|
||||||
|
<v-card-text>
|
||||||
|
<p><strong>Status:</strong> {{ camera.isActive ? 'Ativo' : 'Inativo' }}</p>
|
||||||
|
<p><strong>Descrição:</strong> {{ camera.description }}</p>
|
||||||
|
<p><strong>Data de Registro:</strong> {{ camera.registrationDate }}</p>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
<!-- Pesquisar Tab -->
|
<!-- Pesquisar Tab -->
|
||||||
<v-form v-if="activeTab === 2" @submit.prevent="searchCameraModels">
|
<v-form v-if="activeTab === 2" @submit.prevent="searchCameraModels">
|
||||||
<v-row>
|
<v-row>
|
||||||
@ -68,6 +83,20 @@
|
|||||||
<v-btn type="submit" color="primary">Pesquisar</v-btn>
|
<v-btn type="submit" color="primary">Pesquisar</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
<v-row v-if="searchResults.length">
|
||||||
|
<v-col v-for="(camera, index) in searchResults" :key="index" cols="12" md="4">
|
||||||
|
<v-card outlined>
|
||||||
|
<v-card-title>{{ camera.name }}</v-card-title>
|
||||||
|
<v-card-subtitle>{{ camera.id }}</v-card-subtitle>
|
||||||
|
<v-card-text>
|
||||||
|
<p><strong>Descrição:</strong> {{ camera.description }}</p>
|
||||||
|
<p><strong>Status:</strong> {{ camera.isActive ? 'Ativo' : 'Inativo' }}</p>
|
||||||
|
<p><strong>Data de Registro:</strong> {{ camera.registrationDate }}</p>
|
||||||
|
<p><strong>Treinada:</strong> {{ camera.isTrained ? 'Sim' : 'Não' }}</p>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
</v-form>
|
</v-form>
|
||||||
|
|
||||||
<!-- Treino Tab -->
|
<!-- Treino Tab -->
|
||||||
@ -147,6 +176,11 @@
|
|||||||
{{ face.isActive ? 'Ativo' : 'Inativo' }}
|
{{ face.isActive ? 'Ativo' : 'Inativo' }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
|
<v-list-item-action>
|
||||||
|
<v-btn icon @click="editFaceName(face)">
|
||||||
|
<v-icon>mdi-pencil</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-list-item-action>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
@ -217,6 +251,11 @@ export default {
|
|||||||
untrainedCameras: [
|
untrainedCameras: [
|
||||||
{ id: 'CAM003', name: 'Câmera Estacionamento', brand: 'Dahua' }
|
{ 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-03T08:30', isTrained: true },
|
||||||
|
{ id: 'CAM002', name: 'Câmera Corredor', description: 'Câmera do corredor principal', isActive: false, registrationDate: '2025-01-28T14:00', isTrained: false }
|
||||||
|
],
|
||||||
|
searchResults: [],
|
||||||
identifiedFaces: [
|
identifiedFaces: [
|
||||||
{
|
{
|
||||||
id: 'USER001',
|
id: 'USER001',
|
||||||
@ -248,6 +287,10 @@ export default {
|
|||||||
},
|
},
|
||||||
searchCameraModels() {
|
searchCameraModels() {
|
||||||
console.log('Critérios de pesquisa:', this.searchCriteria);
|
console.log('Critérios de pesquisa:', this.searchCriteria);
|
||||||
|
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))
|
||||||
|
);
|
||||||
},
|
},
|
||||||
startTraining() {
|
startTraining() {
|
||||||
if (this.selectedCameraForTraining) {
|
if (this.selectedCameraForTraining) {
|
||||||
@ -287,7 +330,10 @@ export default {
|
|||||||
},
|
},
|
||||||
confirmAssignments() {
|
confirmAssignments() {
|
||||||
console.log('Atribuições confirmadas:', this.unidentifiedFaces);
|
console.log('Atribuições confirmadas:', this.unidentifiedFaces);
|
||||||
|
},
|
||||||
|
editFaceName(face) {
|
||||||
|
console.log('Editando rosto:', face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,88 +1,82 @@
|
|||||||
<template>
|
<template>
|
||||||
<app-layout>
|
<v-container>
|
||||||
<v-container>
|
<v-card>
|
||||||
<v-card>
|
<v-card-title>
|
||||||
<v-card-title>
|
Usuários
|
||||||
Usuários
|
<v-spacer></v-spacer>
|
||||||
<v-spacer></v-spacer>
|
<v-text-field
|
||||||
<v-text-field
|
v-model="search"
|
||||||
v-model="search"
|
append-icon="mdi-magnify"
|
||||||
append-icon="mdi-magnify"
|
label="Pesquisar"
|
||||||
label="Pesquisar"
|
single-line
|
||||||
single-line
|
hide-details
|
||||||
hide-details
|
class="mr-4"
|
||||||
class="mr-4"
|
></v-text-field>
|
||||||
></v-text-field>
|
<v-btn color="primary" @click="openUserDialog()">
|
||||||
<v-btn color="primary" @click="openUserDialog()">
|
+ Novo usuário
|
||||||
+ Novo usuário
|
</v-btn>
|
||||||
</v-btn>
|
</v-card-title>
|
||||||
</v-card-title>
|
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-data-table
|
<v-data-table
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
:items="users"
|
:items="users"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:search="search"
|
:search="search"
|
||||||
>
|
>
|
||||||
<template v-slot:status="{ item }">
|
<template v-slot:status="{ item }">
|
||||||
<v-chip
|
<v-chip
|
||||||
:color="getStatusColor(item.status)"
|
:color="getStatusColor(item.status)"
|
||||||
small
|
small
|
||||||
>
|
>
|
||||||
{{ item.status }}
|
{{ item.status }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:actions="{ item }">
|
<template v-slot:actions="{ item }">
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
small
|
small
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
v-on="on"
|
v-on="on"
|
||||||
@click="editUser(item)"
|
@click="editUser(item)"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-pencil</v-icon>
|
<v-icon>mdi-pencil</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<span>Editar</span>
|
<span>Editar</span>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
|
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{ on, attrs }">
|
<template v-slot:activator="{ on, attrs }">
|
||||||
<v-btn
|
<v-btn
|
||||||
icon
|
icon
|
||||||
small
|
small
|
||||||
color="error"
|
color="error"
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
v-on="on"
|
v-on="on"
|
||||||
@click="confirmDelete(item)"
|
@click="confirmDelete(item)"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-delete</v-icon>
|
<v-icon>mdi-delete</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<span>Deletar</span>
|
<span>Deletar</span>
|
||||||
</v-tooltip>
|
</v-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
</v-container>
|
||||||
<!-- Restante do código permanece o mesmo -->
|
|
||||||
</v-container>
|
|
||||||
</app-layout>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AppLayout from '@/components/AppLayout.vue'
|
|
||||||
import { userService } from '@/services/api'
|
import { userService } from '@/services/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'UsersList',
|
name: 'UsersList',
|
||||||
components: { AppLayout },
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
loading: false,
|
loading: false,
|
||||||
dialog: false,
|
dialog: false,
|
||||||
@ -231,4 +225,4 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user