Criado seção de histórico
This commit is contained in:
parent
523d6924c3
commit
51c9f51f4f
|
|
@ -403,7 +403,7 @@ namespace AgroBase.Models.Modules
|
|||
RPM_SP = RpmCorrigido;
|
||||
FatorCompensacaoCurvasAnterior = FatorCompensacaoCurvas;
|
||||
|
||||
Variaveis.OperacaoEmAndamento.SimulacaoRpmControle = Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP;
|
||||
Variaveis.OperacaoEmAndamento.SimulacaoRpmControle = _Controle.PercentualVelocidadeSP;
|
||||
//Console.WriteLine($"RPM Atualizado para {Variaveis.OperacaoEmAndamento.SimulacaoRpmControle}");
|
||||
|
||||
switch (DirecaoAtual)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
|
@ -615,4 +616,132 @@ public class EthernetService
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
public class StatusRedeInfo
|
||||
{
|
||||
public bool AdaptadorEncontrado { get; set; }
|
||||
public bool AdaptadorOperacional { get; set; }
|
||||
public bool CaboConectado { get; set; }
|
||||
public bool IpValido { get; set; }
|
||||
public bool GatewayValido { get; set; }
|
||||
|
||||
public string NomeInterface { get; set; } = "";
|
||||
public string Ip { get; set; } = "";
|
||||
public string Mascara { get; set; } = "";
|
||||
public string Gateway { get; set; } = "";
|
||||
|
||||
public bool RedeOk { get; set; }
|
||||
public string Detalhes { get; set; } = "";
|
||||
}
|
||||
|
||||
public static StatusRedeInfo ObterStatusRede(string nomeInterface = null, bool exigirGateway = false)
|
||||
{
|
||||
var info = new StatusRedeInfo();
|
||||
|
||||
try
|
||||
{
|
||||
var interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(ni =>
|
||||
ni.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
|
||||
ni.NetworkInterfaceType != NetworkInterfaceType.Tunnel &&
|
||||
ni.Description.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) < 0 &&
|
||||
ni.Name.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) < 0)
|
||||
.ToList();
|
||||
|
||||
NetworkInterface niSelecionada = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(nomeInterface))
|
||||
{
|
||||
niSelecionada = interfaces.FirstOrDefault(ni =>
|
||||
ni.Name.Equals(nomeInterface, StringComparison.OrdinalIgnoreCase) ||
|
||||
ni.Description.Equals(nomeInterface, StringComparison.OrdinalIgnoreCase) ||
|
||||
ni.Name.IndexOf(nomeInterface, StringComparison.OrdinalIgnoreCase) >= 0 ||
|
||||
ni.Description.IndexOf(nomeInterface, StringComparison.OrdinalIgnoreCase) >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
niSelecionada = interfaces
|
||||
.Where(ni =>
|
||||
ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet ||
|
||||
ni.NetworkInterfaceType == NetworkInterfaceType.GigabitEthernet ||
|
||||
ni.Description.IndexOf("Ethernet", StringComparison.OrdinalIgnoreCase) >= 0 ||
|
||||
ni.Name.IndexOf("Ethernet", StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
.OrderByDescending(ni => ni.OperationalStatus == OperationalStatus.Up)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
if (niSelecionada == null)
|
||||
{
|
||||
info.Detalhes = "Nenhum adaptador de rede compatível encontrado.";
|
||||
return info;
|
||||
}
|
||||
|
||||
info.AdaptadorEncontrado = true;
|
||||
info.NomeInterface = niSelecionada.Name;
|
||||
info.AdaptadorOperacional = niSelecionada.OperationalStatus == OperationalStatus.Up;
|
||||
info.CaboConectado = info.AdaptadorOperacional;
|
||||
|
||||
var props = niSelecionada.GetIPProperties();
|
||||
|
||||
var ipv4 = props.UnicastAddresses
|
||||
.FirstOrDefault(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
|
||||
|
||||
var gateway = props.GatewayAddresses
|
||||
.FirstOrDefault(g => g.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
|
||||
|
||||
if (ipv4 != null)
|
||||
{
|
||||
info.Ip = ipv4.Address.ToString();
|
||||
info.Mascara = ipv4.IPv4Mask?.ToString() ?? "";
|
||||
info.IpValido = IpEhValido(info.Ip);
|
||||
}
|
||||
|
||||
if (gateway != null)
|
||||
{
|
||||
info.Gateway = gateway.Address.ToString();
|
||||
info.GatewayValido = IpEhValido(info.Gateway);
|
||||
}
|
||||
|
||||
info.RedeOk =
|
||||
info.AdaptadorEncontrado &&
|
||||
info.CaboConectado &&
|
||||
info.IpValido &&
|
||||
(!exigirGateway || info.GatewayValido);
|
||||
|
||||
info.Detalhes =
|
||||
$"{info.NomeInterface}\n" +
|
||||
$"Cabo: {(info.CaboConectado ? "Conectado" : "Desconectado")}\n" +
|
||||
$"IP: {(!string.IsNullOrWhiteSpace(info.Ip) ? info.Ip : "Não definido")}\n" +
|
||||
$"Máscara: {(!string.IsNullOrWhiteSpace(info.Mascara) ? info.Mascara : "Não definida")}\n" +
|
||||
$"Gateway: {(!string.IsNullOrWhiteSpace(info.Gateway) ? info.Gateway : "Não definido")}\n" +
|
||||
$"Rede OK: {(info.RedeOk ? "Sim" : "Não")}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.RedeOk = false;
|
||||
info.Detalhes = "Erro ao obter status da rede: " + ex.Message;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private static bool IpEhValido(string ip)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ip))
|
||||
return false;
|
||||
|
||||
if (!IPAddress.TryParse(ip, out var endereco))
|
||||
return false;
|
||||
|
||||
if (IPAddress.Any.Equals(endereco))
|
||||
return false;
|
||||
|
||||
// APIPA: geralmente indica ausência de DHCP/conectividade útil
|
||||
if (ip.StartsWith("169.254."))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<ComboBox x:Name="CmbBaseMap" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,10,0" Width="189" SelectionChanged="OnBaseMapChanged"/>
|
||||
|
||||
<Button Content="Carregar Mapa" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Padding="8,4" Background="#2ECC71" Foreground="White" FontWeight="Bold" Click="OnLoadMapClicked"/>
|
||||
<Button Content="Carregar Mapa" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Padding="8,4" Background="#2ECC71" Foreground="White" FontWeight="Bold" Click="OnLoadMapClicked" Visibility="Collapsed"/>
|
||||
<!--<Button Content="Centralizar" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10" Padding="8,4" Background="#2ECC71" Foreground="White" FontWeight="Bold" Click="OnCenterAreaClicked"/>-->
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
@ -930,6 +930,14 @@ namespace OperationControl.Controls
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void LimparRastrosRover(string? roverId, bool limparPredicao = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(roverId))
|
||||
return;
|
||||
|
||||
markers?.ClearMarkerTrail(roverId, limparPredicao);
|
||||
}
|
||||
}
|
||||
|
||||
public class MapMarkerManager
|
||||
|
|
@ -1089,6 +1097,19 @@ namespace OperationControl.Controls
|
|||
UpdateFeatures();
|
||||
}
|
||||
|
||||
|
||||
public void ClearMarkerTrail(string id, bool clearPrediction = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id)) return;
|
||||
|
||||
var marker = _features.FirstOrDefault(x => x.Id == id);
|
||||
if (marker == null) return;
|
||||
|
||||
marker.ClearTrajectory(clearPrediction);
|
||||
_map.Refresh();
|
||||
}
|
||||
|
||||
|
||||
public class MapMarkerDictionaryModel
|
||||
{
|
||||
public void CreateTrajectory(MapControl _map)
|
||||
|
|
@ -1344,6 +1365,34 @@ namespace OperationControl.Controls
|
|||
}
|
||||
|
||||
|
||||
public void ClearTrajectory(bool clearPrediction = true)
|
||||
{
|
||||
_trajFeatures.Clear();
|
||||
|
||||
if (_trajLayer != null)
|
||||
{
|
||||
_trajLayer.DataSource = new MemoryProvider(_trajFeatures);
|
||||
_trajLayer.DataHasChanged();
|
||||
}
|
||||
|
||||
if (clearPrediction)
|
||||
{
|
||||
_predFeatures.Clear();
|
||||
|
||||
if (_predLayer != null)
|
||||
{
|
||||
_predLayer.DataSource = new MemoryProvider(_predFeatures);
|
||||
_predLayer.DataHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// Reseta a posição base do rastro para a posição atual do rover,
|
||||
// evitando que ao voltar a andar ele desenhe uma linha gigante do passado.
|
||||
var (x, y) = Mapsui.Projections.SphericalMercator.FromLonLat(Lon, Lat);
|
||||
Position = new Coordinate(x, y);
|
||||
}
|
||||
|
||||
|
||||
#region TRAJETORIA
|
||||
|
||||
private MemoryProvider _trajProvider;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ namespace OperationControl.Models
|
|||
? $"{Modulo} ({Mod_ID})"
|
||||
: Modulo.ToString();
|
||||
|
||||
return $"[{Rover_ID}] {mod} — {ResumoSeveridade}";
|
||||
//return $"[{Rover_ID}] {mod} — {ResumoSeveridade}";
|
||||
return $"{mod} — {ResumoSeveridade}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ namespace OperationControl.Models
|
|||
{
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
(Dock?.DataContext as DockWindowViewModel)?.AdicionarAlerta(roverId, modulo, severidade, mensagem, modId);
|
||||
Dock?._vm?.AdicionarAlerta(roverId, modulo, severidade, mensagem, modId);
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ namespace OperationControl.Models
|
|||
{
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
(Dock?.DataContext as DockWindowViewModel)?.RemoverAlerta(roverId, modulo, severidade, modId);
|
||||
Dock?._vm?.RemoverAlerta(roverId, modulo, severidade, modId);
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using OperationControl.Services;
|
|||
using AgroMonitor;
|
||||
using Application = System.Windows.Application;
|
||||
using AgroBase.Models.Operacoes;
|
||||
using OperationControl.Windows;
|
||||
|
||||
namespace OperationControl.Models
|
||||
{
|
||||
|
|
@ -15,6 +16,8 @@ namespace OperationControl.Models
|
|||
public static UdpReliableChannel UdpChannel;
|
||||
public static ManualControlSender ControlSenderDir;
|
||||
public static ManualControlSender ControlSenderMov;
|
||||
public static AppShell? Shell => ((App)Application.Current)?.Shell;
|
||||
public static DockWindow? Dock => Shell?.Dock;
|
||||
|
||||
public static void MostrarLog(string message)
|
||||
{
|
||||
|
|
@ -163,11 +166,11 @@ namespace OperationControl.Models
|
|||
rover.UltimoContato = DateTime.Now;
|
||||
}
|
||||
}
|
||||
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(device_id);
|
||||
//((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(device_id);
|
||||
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
((App)Application.Current).Shell.Dock?._vm?.AtualizarDadosTela(rover);
|
||||
Variaveis.Dock?._vm?.AtualizarDadosTela(rover);
|
||||
}));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -195,9 +198,9 @@ namespace OperationControl.Models
|
|||
RoversNaRede[index] = obj;
|
||||
}
|
||||
}
|
||||
((App)Application.Current).Shell.Main?.AtualizarDadosTela_ParametrosOperacao(obj.Controle);
|
||||
((App)Application.Current).Shell.Main?.MAP?.CarregarDadosMapa(obj.Mapa, obj.RuasPercorrer);
|
||||
((App)Application.Current).Shell.Dock?._vm?.AtualizarParametrosRover(obj);
|
||||
//((App)Application.Current).Shell.Main?.AtualizarDadosTela_ParametrosOperacao(obj.Controle);
|
||||
//((App)Application.Current).Shell.Main?.MAP?.CarregarDadosMapa(obj.Mapa, obj.RuasPercorrer);
|
||||
Variaveis.Dock?._vm?.AtualizarParametrosRover(obj);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -211,7 +214,7 @@ namespace OperationControl.Models
|
|||
{
|
||||
dispositivos_ids = dispositivos_ids.Union(RoversNaRede.Select(x => x.RoverId).ToList()).ToList();
|
||||
}
|
||||
((App)Application.Current).Shell.Main?.AtualizarListaDispositivos(dispositivos_ids);
|
||||
//((App)Application.Current).Shell.Main?.AtualizarListaDispositivos(dispositivos_ids);
|
||||
|
||||
RequisitarParametrosOperacao();
|
||||
}
|
||||
|
|
@ -244,24 +247,24 @@ namespace OperationControl.Models
|
|||
rover.DadosLeitura.Momento = DateTime.Now;
|
||||
if (rover.DadosLeitura.Operacao == null) rover.DadosLeitura.Operacao = new OperacaoParametrosDadosOperacaoModel();
|
||||
rover.DadosLeitura.Operacao.Status = AgroBase.Models.Enums.StatusOperacao.Erro;
|
||||
((App)Application.Current)?.Shell?.Main?.AtualizarDadosTela_Telemetria(rover.RoverId);
|
||||
((App)Application.Current)?.Shell?.Main?.AdicionarAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
|
||||
//((App)Application.Current)?.Shell?.Main?.AtualizarDadosTela_Telemetria(rover.RoverId);
|
||||
//((App)Application.Current)?.Shell?.Main?.AdicionarAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
|
||||
|
||||
|
||||
((App)Application.Current)?.Shell?.AdicionarAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
|
||||
((App)Application.Current)?.Shell?.Dock?._vm?._viewOperacaoCenter?.Mapa?.markers?.UpdateMarkerInfo(rover.RoverId, status: AgroBase.Models.Enums.StatusOperacao.Erro);
|
||||
Variaveis.Shell?.AdicionarAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
|
||||
Variaveis.Dock?._vm?._viewOperacaoCenter?.Mapa?.markers?.UpdateMarkerInfo(rover.RoverId, status: AgroBase.Models.Enums.StatusOperacao.Erro);
|
||||
}
|
||||
else
|
||||
{
|
||||
((App)Application.Current)?.Shell?.Main?.RemoverAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
|
||||
((App)Application.Current)?.Shell?.RemoverAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
|
||||
//((App)Application.Current)?.Shell?.Main?.RemoverAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
|
||||
Variaveis.Shell?.RemoverAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
|
||||
}
|
||||
((App)Application.Current)?.Shell?.Dock?._vm?.AtualizarBarraSuperior(rover);
|
||||
Variaveis.Shell?.Dock?._vm?.AtualizarBarraSuperior(rover);
|
||||
}
|
||||
|
||||
Application.Current?.Dispatcher?.BeginInvoke(new Action(() =>
|
||||
{
|
||||
((App)Application.Current)?.Shell?.Dock?._vm?.AtualizarListaRovers(rovers_atual);
|
||||
Variaveis.Shell?.Dock?._vm?.AtualizarListaRovers(rovers_atual);
|
||||
}));
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@
|
|||
<Compile Update="Views\Operacao\Monitoramento\DiagnosticoView.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Views\Operacao\Monitoramento\HistoricoView.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Views\Operacao\Monitoramento\MonitoramentoView.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
|
@ -138,6 +141,9 @@
|
|||
<Page Update="Views\Operacao\Monitoramento\DiagnosticoView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Views\Operacao\Monitoramento\HistoricoView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Views\Operacao\Monitoramento\MonitoramentoView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
|
|
|
|||
|
|
@ -368,8 +368,7 @@ namespace OperationControl.Services
|
|||
}
|
||||
|
||||
Models.Variaveis.MostrarLog(mensagem);
|
||||
((App)Application.Current)?.Shell?.Dock?._vm?._viewPreparacaoMapaBottom?._vm?.FinalizarFixacao(sucesso, mensagem);
|
||||
((App)Application.Current)?.Shell?.Dock?._vm?.FinalizarFixacaoBase(sucesso, mensagem);
|
||||
Models.Variaveis.Dock?._vm?.FinalizarFixacaoBase(sucesso, mensagem);
|
||||
}
|
||||
|
||||
private async Task ConfigurarModuloBase(string porta_usb = "com3", string porta_saida = "com2", int tempo_fixacao = 60)
|
||||
|
|
@ -1223,9 +1222,9 @@ namespace OperationControl.Services
|
|||
{
|
||||
try
|
||||
{
|
||||
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(VariaveisControleOperacao.BaseMarkerID);
|
||||
//((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(VariaveisControleOperacao.BaseMarkerID);
|
||||
|
||||
((App)Application.Current).Shell.Dock?._vm?.AtualizarDadosGnss(UltimaLeitura);
|
||||
Models.Variaveis.Dock?._vm?.AtualizarDadosGnss(UltimaLeitura);
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -248,21 +248,17 @@ namespace OperationControl.ViewModels
|
|||
{
|
||||
try
|
||||
{
|
||||
// 1) Escolhe a interface “ativa” ou a que você usa pra ponte IP
|
||||
// Se você já tem isso fixo, melhor ainda: use sempre a mesma.
|
||||
var interfaces = EthernetService.ObterNomesInterfaces().Where(x => x.Contains("Ativa")).Select(x => x.Split('(')[0].Trim()).ToList();
|
||||
var iface = interfaces[0]; // <-- se tiver
|
||||
// ou se você já sabe o nome: var iface = "Ethernet 2";
|
||||
var interfaces = EthernetService.ObterNomesInterfaces()
|
||||
.Where(x => x.Contains(AppShell.Mock ? "Ativa" : "Ethernet"))
|
||||
.Select(x => x.Split('(')[0].Trim())
|
||||
.ToList();
|
||||
|
||||
var ip = EthernetService.ObterIpAtual(iface);
|
||||
var sub = EthernetService.ObterSubnetMaskAtual(iface);
|
||||
var gw = EthernetService.ObterIpGateway(iface);
|
||||
string? iface = interfaces.FirstOrDefault();
|
||||
|
||||
DetalhesRede = $"{iface}\nIP: {ip}\nMáscara: {sub}\nGateway: {gw}";
|
||||
var status = EthernetService.ObterStatusRede(iface, exigirGateway: false);
|
||||
|
||||
// 2) Define RedeOk do jeito que faz sentido pra você:
|
||||
// exemplo simples: tem IP válido + gateway válido
|
||||
RedeOk = !string.IsNullOrWhiteSpace(ip) && ip != "0.0.0.0";
|
||||
RedeOk = status.RedeOk;
|
||||
DetalhesRede = status.Detalhes;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,397 @@
|
|||
using OperationControl.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
|
||||
{
|
||||
public class HistoricoViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public HistoricoViewModel()
|
||||
{
|
||||
EventosView = CollectionViewSource.GetDefaultView(Eventos);
|
||||
EventosView.Filter = FiltrarEvento;
|
||||
|
||||
_ordenacaoSelecionada = "Mais recentes";
|
||||
|
||||
AplicarOrdenacao();
|
||||
AtualizarFiltros();
|
||||
}
|
||||
|
||||
private List<MotivoTopBarModel> _eventosTopBarAnteriores = new();
|
||||
|
||||
private ObservableCollection<HistoricoOperacaoItemModel> _eventos = new();
|
||||
public ObservableCollection<HistoricoOperacaoItemModel> Eventos
|
||||
{
|
||||
get => _eventos;
|
||||
set
|
||||
{
|
||||
_eventos = value;
|
||||
OnPropertyChanged(nameof(Eventos));
|
||||
|
||||
EventosView = CollectionViewSource.GetDefaultView(Eventos);
|
||||
EventosView.Filter = FiltrarEvento;
|
||||
AplicarOrdenacao();
|
||||
|
||||
OnPropertyChanged(nameof(EventosView));
|
||||
OnPropertyChanged(nameof(QuantidadeEventos));
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
}
|
||||
}
|
||||
|
||||
private ICollectionView _eventosView;
|
||||
public ICollectionView EventosView
|
||||
{
|
||||
get => _eventosView;
|
||||
set
|
||||
{
|
||||
_eventosView = value;
|
||||
OnPropertyChanged(nameof(EventosView));
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
}
|
||||
}
|
||||
|
||||
public int QuantidadeEventos => Eventos?.Count ?? 0;
|
||||
|
||||
public int QuantidadeEventosFiltrados
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EventosView == null) return 0;
|
||||
return EventosView.Cast<object>().Count();
|
||||
}
|
||||
}
|
||||
|
||||
private string _textoBusca;
|
||||
public string TextoBusca
|
||||
{
|
||||
get => _textoBusca;
|
||||
set
|
||||
{
|
||||
if (_textoBusca == value) return;
|
||||
_textoBusca = value;
|
||||
OnPropertyChanged(nameof(TextoBusca));
|
||||
AtualizarFiltros();
|
||||
}
|
||||
}
|
||||
|
||||
private string _roverIdSelecionado;
|
||||
public string RoverIdSelecionado
|
||||
{
|
||||
get => _roverIdSelecionado;
|
||||
set
|
||||
{
|
||||
if (_roverIdSelecionado == value) return;
|
||||
_roverIdSelecionado = value;
|
||||
OnPropertyChanged(nameof(RoverIdSelecionado));
|
||||
AtualizarFiltros();
|
||||
}
|
||||
}
|
||||
|
||||
private string _tipoTransicaoSelecionado = "Todos";
|
||||
public string TipoTransicaoSelecionado
|
||||
{
|
||||
get => _tipoTransicaoSelecionado;
|
||||
set
|
||||
{
|
||||
if (_tipoTransicaoSelecionado == value) return;
|
||||
_tipoTransicaoSelecionado = value;
|
||||
OnPropertyChanged(nameof(TipoTransicaoSelecionado));
|
||||
AtualizarFiltros();
|
||||
}
|
||||
}
|
||||
|
||||
private string _statusSelecionado = "Todos";
|
||||
public string StatusSelecionado
|
||||
{
|
||||
get => _statusSelecionado;
|
||||
set
|
||||
{
|
||||
if (_statusSelecionado == value) return;
|
||||
_statusSelecionado = value;
|
||||
OnPropertyChanged(nameof(StatusSelecionado));
|
||||
AtualizarFiltros();
|
||||
}
|
||||
}
|
||||
|
||||
private string _fonteSelecionada = "Todas";
|
||||
public string FonteSelecionada
|
||||
{
|
||||
get => _fonteSelecionada;
|
||||
set
|
||||
{
|
||||
if (_fonteSelecionada == value) return;
|
||||
_fonteSelecionada = value;
|
||||
OnPropertyChanged(nameof(FonteSelecionada));
|
||||
AtualizarFiltros();
|
||||
}
|
||||
}
|
||||
|
||||
private string _ordenacaoSelecionada;
|
||||
public string OrdenacaoSelecionada
|
||||
{
|
||||
get => _ordenacaoSelecionada;
|
||||
set
|
||||
{
|
||||
if (_ordenacaoSelecionada == value) return;
|
||||
_ordenacaoSelecionada = value;
|
||||
OnPropertyChanged(nameof(OrdenacaoSelecionada));
|
||||
AplicarOrdenacao();
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> TiposTransicaoDisponiveis { get; } = new()
|
||||
{
|
||||
"Todos",
|
||||
"INICIO",
|
||||
"FIM",
|
||||
"MUDANCA"
|
||||
};
|
||||
|
||||
public List<string> StatusDisponiveis { get; } = new()
|
||||
{
|
||||
"Todos",
|
||||
"Falha",
|
||||
"Alerta",
|
||||
"Desconectado",
|
||||
"Operante",
|
||||
"Conectado"
|
||||
};
|
||||
|
||||
public List<string> FontesDisponiveis { get; } = new()
|
||||
{
|
||||
"Todas",
|
||||
"Normal",
|
||||
"Comunicacao",
|
||||
"Emergencia",
|
||||
"Pausa",
|
||||
"Controle",
|
||||
"Trajetoria",
|
||||
"ModuloCritico",
|
||||
"NCP",
|
||||
"AlertaModulo"
|
||||
};
|
||||
|
||||
public List<string> OrdenacoesDisponiveis { get; } = new()
|
||||
{
|
||||
"Mais recentes",
|
||||
"Mais antigos",
|
||||
"Título (A-Z)",
|
||||
"Fonte (A-Z)",
|
||||
"Status"
|
||||
};
|
||||
|
||||
private bool FiltrarEvento(object obj)
|
||||
{
|
||||
if (obj is not HistoricoOperacaoItemModel ev)
|
||||
return false;
|
||||
|
||||
// filtro padrão por rover selecionado
|
||||
if (!string.IsNullOrWhiteSpace(RoverIdSelecionado) &&
|
||||
!string.Equals(ev.RoverId, RoverIdSelecionado, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TipoTransicaoSelecionado) &&
|
||||
TipoTransicaoSelecionado != "Todos" &&
|
||||
!string.Equals(ev.TipoTransicao, TipoTransicaoSelecionado, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(StatusSelecionado) &&
|
||||
StatusSelecionado != "Todos" &&
|
||||
!string.Equals(ev.StatusVisual.ToString(), StatusSelecionado, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FonteSelecionada) &&
|
||||
FonteSelecionada != "Todas" &&
|
||||
!string.Equals(ev.Fonte, FonteSelecionada, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TextoBusca))
|
||||
{
|
||||
var busca = TextoBusca.Trim();
|
||||
|
||||
bool encontrou =
|
||||
(ev.Titulo?.Contains(busca, StringComparison.OrdinalIgnoreCase) ?? false) ||
|
||||
(ev.Descricao?.Contains(busca, StringComparison.OrdinalIgnoreCase) ?? false) ||
|
||||
(ev.Fonte?.Contains(busca, StringComparison.OrdinalIgnoreCase) ?? false) ||
|
||||
(ev.RoverId?.Contains(busca, StringComparison.OrdinalIgnoreCase) ?? false) ||
|
||||
(ev.TipoTransicao?.Contains(busca, StringComparison.OrdinalIgnoreCase) ?? false) ||
|
||||
(ev.Modulo?.ToString().Contains(busca, StringComparison.OrdinalIgnoreCase) ?? false);
|
||||
|
||||
if (!encontrou)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AtualizarFiltros()
|
||||
{
|
||||
EventosView?.Refresh();
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
}
|
||||
|
||||
public void AplicarOrdenacao()
|
||||
{
|
||||
if (EventosView == null) return;
|
||||
|
||||
using (EventosView.DeferRefresh())
|
||||
{
|
||||
EventosView.SortDescriptions.Clear();
|
||||
|
||||
switch (OrdenacaoSelecionada)
|
||||
{
|
||||
case "Mais antigos":
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.DataHora), ListSortDirection.Ascending));
|
||||
break;
|
||||
|
||||
case "Título (A-Z)":
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.Titulo), ListSortDirection.Ascending));
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.DataHora), ListSortDirection.Descending));
|
||||
break;
|
||||
|
||||
case "Fonte (A-Z)":
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.Fonte), ListSortDirection.Ascending));
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.DataHora), ListSortDirection.Descending));
|
||||
break;
|
||||
|
||||
case "Status":
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.StatusVisual), ListSortDirection.Ascending));
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.DataHora), ListSortDirection.Descending));
|
||||
break;
|
||||
|
||||
default:
|
||||
EventosView.SortDescriptions.Add(new SortDescription(nameof(HistoricoOperacaoItemModel.DataHora), ListSortDirection.Descending));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
}
|
||||
|
||||
public void LimparBusca()
|
||||
{
|
||||
TextoBusca = string.Empty;
|
||||
}
|
||||
|
||||
public void ResetarFiltros()
|
||||
{
|
||||
RoverIdSelecionado = VariaveisControleOperacao.SelectedRoverId;
|
||||
TextoBusca = string.Empty;
|
||||
TipoTransicaoSelecionado = "Todos";
|
||||
StatusSelecionado = "Todos";
|
||||
FonteSelecionada = "Todas";
|
||||
OrdenacaoSelecionada = "Mais recentes";
|
||||
AtualizarFiltros();
|
||||
}
|
||||
|
||||
public void CompararERegistrarMudancasEventos(string roverId, List<MotivoTopBarModel> eventosAtuais)
|
||||
{
|
||||
string Chave(MotivoTopBarModel e) =>
|
||||
$"{e.Fonte}|{e.Titulo}|{e.Descricao}|{e.Modulo}|{e.StatusVisual}";
|
||||
|
||||
var atuais = eventosAtuais?
|
||||
.GroupBy(Chave)
|
||||
.ToDictionary(g => g.Key, g => g.First())
|
||||
?? new Dictionary<string, MotivoTopBarModel>();
|
||||
|
||||
var anteriores = _eventosTopBarAnteriores?
|
||||
.GroupBy(Chave)
|
||||
.ToDictionary(g => g.Key, g => g.First())
|
||||
?? new Dictionary<string, MotivoTopBarModel>();
|
||||
|
||||
foreach (var chave in anteriores.Keys.Except(atuais.Keys))
|
||||
RegistrarLogEvento(roverId, "FIM", anteriores[chave]);
|
||||
|
||||
foreach (var chave in atuais.Keys.Except(anteriores.Keys))
|
||||
RegistrarLogEvento(roverId, "INICIO", atuais[chave]);
|
||||
|
||||
_eventosTopBarAnteriores = eventosAtuais?
|
||||
.Select(x => new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = x.Prioridade,
|
||||
Fonte = x.Fonte,
|
||||
Titulo = x.Titulo,
|
||||
Descricao = x.Descricao,
|
||||
StatusVisual = x.StatusVisual,
|
||||
Modulo = x.Modulo
|
||||
})
|
||||
.ToList() ?? new List<MotivoTopBarModel>();
|
||||
|
||||
_roverIdSelecionado = VariaveisControleOperacao.SelectedRoverId;
|
||||
|
||||
OnPropertyChanged(nameof(QuantidadeEventos));
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
OnPropertyChanged(nameof(RoverIdSelecionado));
|
||||
}
|
||||
|
||||
private void RegistrarLogEvento(string roverId, string tipoTransicao, MotivoTopBarModel ev)
|
||||
{
|
||||
if (ev == null) return;
|
||||
|
||||
var item = new HistoricoOperacaoItemModel
|
||||
{
|
||||
DataHora = DateTime.Now,
|
||||
RoverId = roverId,
|
||||
Tipo = TipoHistoricoOperacao.Operacao,
|
||||
TipoTransicao = tipoTransicao,
|
||||
Fonte = ev.Fonte,
|
||||
Titulo = ev.Titulo,
|
||||
Descricao = ev.Descricao,
|
||||
StatusVisual = ev.StatusVisual,
|
||||
Modulo = ev.Modulo
|
||||
};
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
Eventos.Insert(0, item);
|
||||
|
||||
if (Eventos.Count > 2000)
|
||||
Eventos.RemoveAt(Eventos.Count - 1);
|
||||
|
||||
AtualizarFiltros();
|
||||
OnPropertyChanged(nameof(QuantidadeEventos));
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
}));
|
||||
}
|
||||
|
||||
public void RegistrarHistoricoAlerta(string tipoTransicao, AlertaModel alerta)
|
||||
{
|
||||
if (alerta == null) return;
|
||||
|
||||
var item = new HistoricoOperacaoItemModel
|
||||
{
|
||||
DataHora = DateTime.Now,
|
||||
RoverId = alerta.Rover_ID,
|
||||
Tipo = TipoHistoricoOperacao.Alerta,
|
||||
TipoTransicao = tipoTransicao,
|
||||
Fonte = "AlertaModulo",
|
||||
Titulo = alerta.Titulo,
|
||||
Descricao = alerta.Mensagem,
|
||||
SeveridadeAlerta = alerta.Severidade,
|
||||
Modulo = alerta.Modulo,
|
||||
ModId = alerta.Mod_ID
|
||||
};
|
||||
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
Eventos.Insert(0, item);
|
||||
|
||||
if (Eventos.Count > 2000)
|
||||
Eventos.RemoveAt(Eventos.Count - 1);
|
||||
|
||||
AtualizarFiltros();
|
||||
OnPropertyChanged(nameof(QuantidadeEventos));
|
||||
OnPropertyChanged(nameof(QuantidadeEventosFiltrados));
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged(string nome)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using OperationControl.Models;
|
||||
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Threading;
|
||||
|
|
@ -8,6 +9,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
{
|
||||
public class OperacaoBottomViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private HistoricoViewModel? historicoVm => Variaveis.Dock?._vm?._viewOperacaoCenter?.Historico?._vm;
|
||||
public ObservableCollection<AlertaModel> AlertasAtivos { get; } = new();
|
||||
|
||||
private AlertaModel _toastAlerta;
|
||||
|
|
@ -87,11 +89,21 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
|
||||
AlertasAtivos.Add(alerta);
|
||||
MostrarToast(alerta);
|
||||
|
||||
historicoVm?.RegistrarHistoricoAlerta("INICIO", alerta);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool mudouMensagem = existente.Mensagem != mensagem;
|
||||
bool mudouSeveridade = existente.Severidade != severidade;
|
||||
|
||||
existente.Mensagem = mensagem;
|
||||
existente.Severidade = severidade;
|
||||
|
||||
if (mudouMensagem || mudouSeveridade)
|
||||
{
|
||||
historicoVm?.RegistrarHistoricoAlerta("MUDANCA", existente);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
@ -107,7 +119,10 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
(severidade != null ? x.Severidade == severidade : true));
|
||||
|
||||
if (alerta != null)
|
||||
{
|
||||
historicoVm?.RegistrarHistoricoAlerta("FIM", alerta);
|
||||
AlertasAtivos.Remove(alerta);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +281,8 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
{
|
||||
var alertaRemover = mapaAtual[chave];
|
||||
|
||||
historicoVm?.RegistrarHistoricoAlerta("FIM", alertaRemover);
|
||||
|
||||
AlertasAtivos.Remove(alertaRemover);
|
||||
|
||||
if (ToastAlerta == alertaRemover)
|
||||
|
|
@ -284,6 +301,8 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
esperado.CriadoEm = agora;
|
||||
AlertasAtivos.Add(esperado);
|
||||
MostrarToast(esperado);
|
||||
|
||||
historicoVm?.RegistrarHistoricoAlerta("INICIO", esperado);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -296,11 +315,11 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
{
|
||||
existente.Mensagem = esperado.Mensagem;
|
||||
existente.Severidade = esperado.Severidade;
|
||||
|
||||
// Se quiser que Timestamp represente "última mudança", mantém isso:
|
||||
existente.AtualizadoEm = agora;
|
||||
|
||||
MostrarToast(existente);
|
||||
|
||||
historicoVm?.RegistrarHistoricoAlerta("MUDANCA", existente);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
OnPropertyChanged(nameof(ExibirMapa));
|
||||
OnPropertyChanged(nameof(ExibirDiagnostico));
|
||||
OnPropertyChanged(nameof(ExibirMonitoramento));
|
||||
OnPropertyChanged(nameof(ExibirHistorico));
|
||||
OnPropertyChanged(nameof(TituloCentro));
|
||||
OnPropertyChanged(nameof(SubtituloCentro));
|
||||
}
|
||||
|
|
@ -49,6 +50,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
public bool ExibirMapa => ConteudoAtual == OperacaoCenterConteudo.Mapa;
|
||||
public bool ExibirDiagnostico => ConteudoAtual == OperacaoCenterConteudo.Diagnostico;
|
||||
public bool ExibirMonitoramento => ConteudoAtual == OperacaoCenterConteudo.Monitoramento;
|
||||
public bool ExibirHistorico => ConteudoAtual == OperacaoCenterConteudo.Historico;
|
||||
|
||||
public string TituloCentro
|
||||
{
|
||||
|
|
@ -101,6 +103,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
SecaoRightBar.Controle => OperacaoCenterConteudo.Monitoramento,
|
||||
SecaoRightBar.Parametrizacao => OperacaoCenterConteudo.Mapa,
|
||||
SecaoRightBar.Menu => OperacaoCenterConteudo.Monitoramento,
|
||||
SecaoRightBar.Historico => OperacaoCenterConteudo.Historico,
|
||||
|
||||
_ => OperacaoCenterConteudo.Mapa
|
||||
};
|
||||
|
|
@ -142,6 +145,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
{
|
||||
Mapa = 1,
|
||||
Diagnostico = 2,
|
||||
Monitoramento = 3
|
||||
Monitoramento = 3,
|
||||
Historico = 4,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Variaveis.Dock?._vm?._viewOperacaoCenter?.Mapa?.LimparRastrosRover(VariaveisControleOperacao.RoverEmFoco?.RoverId);
|
||||
if ((dadosRover?.Operacao?.Status ?? StatusOperacao.NaoIniciado) == StatusOperacao.Concluido)
|
||||
{
|
||||
VariaveisControleOperacao.EnviarComandoIniciarOperacao(false, false);
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
}
|
||||
}
|
||||
|
||||
public bool EmMenu => SecaoAtual == SecaoRightBar.Menu || SecaoAtual == SecaoRightBar.Diagnostico;
|
||||
public bool EmMenu => new List<SecaoRightBar>() { SecaoRightBar.Menu, SecaoRightBar.Diagnostico, SecaoRightBar.Historico }.Contains(SecaoAtual);
|
||||
public bool EmResumo => SecaoAtual == SecaoRightBar.Resumo;
|
||||
public bool EmParametrizacao => SecaoAtual == SecaoRightBar.Parametrizacao;
|
||||
public bool EmControle => SecaoAtual == SecaoRightBar.Controle;
|
||||
|
|
@ -264,7 +264,8 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
Resumo = 2,
|
||||
Diagnostico = 3,
|
||||
Parametrizacao = 4,
|
||||
Controle = 5
|
||||
Controle = 5,
|
||||
Historico = 6,
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using Brushes = System.Windows.Media.Brushes;
|
|||
using ColorConverter = System.Windows.Media.ColorConverter;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using static AgroBase.Models.Enums;
|
||||
using OperationControl.Models;
|
||||
|
||||
namespace OperationControl.ViewModels.Views.Operacao
|
||||
{
|
||||
|
|
@ -173,4 +174,159 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
public StatusModulo StatusVisual { get; set; }
|
||||
public T_Code? Modulo { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class LogEventoOperacaoModel
|
||||
{
|
||||
public DateTime DataHora { get; set; }
|
||||
public string RoverId { get; set; }
|
||||
public string TipoTransicao { get; set; } // INICIO / FIM / MUDANCA
|
||||
public string Fonte { get; set; }
|
||||
public string Titulo { get; set; }
|
||||
public string Descricao { get; set; }
|
||||
public StatusModulo StatusVisual { get; set; }
|
||||
public T_Code? Modulo { get; set; }
|
||||
|
||||
public string Hora => DataHora.ToString("HH:mm:ss");
|
||||
public string DataHoraCompleta => DataHora.ToString("dd/MM/yyyy HH:mm:ss");
|
||||
|
||||
public string Subtitulo
|
||||
{
|
||||
get
|
||||
{
|
||||
var moduloTxt = Modulo?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(moduloTxt))
|
||||
return $"{Fonte} • {moduloTxt} • {RoverId}";
|
||||
|
||||
return $"{Fonte} • {RoverId}";
|
||||
}
|
||||
}
|
||||
|
||||
public Brush CorAccent
|
||||
{
|
||||
get
|
||||
{
|
||||
return StatusVisual switch
|
||||
{
|
||||
StatusModulo.Falha => Brushes.IndianRed,
|
||||
StatusModulo.Desconectado => Brushes.DarkRed,
|
||||
StatusModulo.Alerta => Brushes.Goldenrod,
|
||||
StatusModulo.Operante => Brushes.ForestGreen,
|
||||
StatusModulo.Conectado => Brushes.SteelBlue,
|
||||
_ => Brushes.Gray
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public Brush CorBadge
|
||||
{
|
||||
get
|
||||
{
|
||||
return TipoTransicao switch
|
||||
{
|
||||
"INICIO" => Brushes.OrangeRed,
|
||||
"FIM" => Brushes.SeaGreen,
|
||||
"MUDANCA" => Brushes.SteelBlue,
|
||||
_ => Brushes.DimGray
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HistoricoOperacaoItemModel
|
||||
{
|
||||
public DateTime DataHora { get; set; }
|
||||
public string RoverId { get; set; }
|
||||
|
||||
public TipoHistoricoOperacao Tipo { get; set; } // Operacao ou Alerta
|
||||
public string TipoTransicao { get; set; } // INICIO / FIM / MUDANCA
|
||||
|
||||
public string Fonte { get; set; } // ex: Controle, Trajetoria, AlertaModulo
|
||||
public string Titulo { get; set; }
|
||||
public string Descricao { get; set; }
|
||||
|
||||
public StatusModulo? StatusVisual { get; set; } // para eventos operacionais
|
||||
public SeveridadeAlerta? SeveridadeAlerta { get; set; } // para alertas
|
||||
|
||||
public T_Code? Modulo { get; set; }
|
||||
public string? ModId { get; set; }
|
||||
|
||||
public string Hora => DataHora.ToString("HH:mm:ss");
|
||||
public string DataHoraCompleta => DataHora.ToString("dd/MM/yyyy HH:mm:ss");
|
||||
|
||||
public string Subtitulo
|
||||
{
|
||||
get
|
||||
{
|
||||
var partes = new List<string>();
|
||||
|
||||
partes.Add(Tipo == TipoHistoricoOperacao.Alerta ? "Alerta" : "Operação");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Fonte))
|
||||
partes.Add(Fonte);
|
||||
|
||||
if (Modulo.HasValue)
|
||||
partes.Add(Modulo.Value.ToString());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ModId))
|
||||
partes.Add(ModId);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(RoverId))
|
||||
partes.Add(RoverId);
|
||||
|
||||
return string.Join(" • ", partes);
|
||||
}
|
||||
}
|
||||
|
||||
public Brush CorAccent
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Tipo == TipoHistoricoOperacao.Alerta)
|
||||
{
|
||||
return SeveridadeAlerta switch
|
||||
{
|
||||
Models.SeveridadeAlerta.Warning => Brushes.Goldenrod,
|
||||
Models.SeveridadeAlerta.Error => Brushes.IndianRed,
|
||||
Models.SeveridadeAlerta.Critical => Brushes.DarkRed,
|
||||
_ => Brushes.SteelBlue
|
||||
};
|
||||
}
|
||||
|
||||
return StatusVisual switch
|
||||
{
|
||||
StatusModulo.Falha => Brushes.IndianRed,
|
||||
StatusModulo.Desconectado => Brushes.DarkRed,
|
||||
StatusModulo.Alerta => Brushes.Goldenrod,
|
||||
StatusModulo.Operante => Brushes.ForestGreen,
|
||||
StatusModulo.Conectado => Brushes.SteelBlue,
|
||||
_ => Brushes.Gray
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public Brush CorBadge
|
||||
{
|
||||
get
|
||||
{
|
||||
return TipoTransicao switch
|
||||
{
|
||||
"INICIO" => Brushes.OrangeRed,
|
||||
"FIM" => Brushes.SeaGreen,
|
||||
"MUDANCA" => Brushes.SteelBlue,
|
||||
_ => Brushes.DimGray
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public enum TipoHistoricoOperacao
|
||||
{
|
||||
Operacao = 0,
|
||||
Alerta = 1
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -374,6 +374,9 @@ namespace OperationControl.ViewModels
|
|||
double tempoSemResposta = (DateTime.Now - rover.UltimoContato).TotalSeconds;
|
||||
bool semComunicacao = !AppShell.Mock && tempoSemResposta >= VariaveisControleOperacao.TempoRoverVivo;
|
||||
|
||||
// ============================
|
||||
// 0) Perda de comunicação
|
||||
// ============================
|
||||
if (semComunicacao)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
|
|
@ -386,11 +389,11 @@ namespace OperationControl.ViewModels
|
|||
});
|
||||
}
|
||||
|
||||
if (obj.ModulosSaude?.All(x => (x?.status ?? StatusModulo.Desconectado) == StatusModulo.Desconectado) ?? false)
|
||||
{
|
||||
// ============================
|
||||
// 0) NCP desconectado
|
||||
// ============================
|
||||
if (obj.ModulosSaude?.All(x => (x?.status ?? StatusModulo.Desconectado) == StatusModulo.Desconectado) ?? false)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 1100,
|
||||
|
|
@ -484,6 +487,14 @@ namespace OperationControl.ViewModels
|
|||
(x?.Utilizar ?? false) &&
|
||||
(x?.Mandatorio ?? false)
|
||||
) ?? false)
|
||||
) ||
|
||||
(
|
||||
(mod?.status ?? StatusModulo.Desconectado) == StatusModulo.Alerta &&
|
||||
(rover?.ModulosMandatorios?.Any(x =>
|
||||
(x?.Dispositivo ?? T_Code.Vzo) == (mod?.modulo ?? T_Code.Vzo) &&
|
||||
(x?.Utilizar ?? false) &&
|
||||
(x?.Mandatorio ?? false)
|
||||
) ?? false)
|
||||
)
|
||||
)
|
||||
.ToList() ?? new List<AgroBase.Models.Operadores.ManagerWorkerMessageResponseModulosPendentesModel>();
|
||||
|
|
@ -500,8 +511,32 @@ namespace OperationControl.ViewModels
|
|||
(x?.Utilizar ?? false) &&
|
||||
(x?.Mandatorio ?? false)
|
||||
) ?? false);
|
||||
bool moduloMandatorioAlerta =
|
||||
(modulo?.status ?? StatusModulo.Desconectado) == StatusModulo.Alerta &&
|
||||
(rover?.ModulosMandatorios?.Any(x =>
|
||||
(x?.Dispositivo ?? T_Code.Vzo) == (modulo?.modulo ?? T_Code.Vzo) &&
|
||||
(x?.Utilizar ?? false) &&
|
||||
(x?.Mandatorio ?? false)
|
||||
) ?? false);
|
||||
|
||||
// Caso 1: condições operacionais severas
|
||||
// Caso 1: módulo mandatório não operante
|
||||
if (moduloMandatorioNaoOperante)
|
||||
{
|
||||
var statusTexto = (modulo?.status ?? StatusModulo.Desconectado).ToString();
|
||||
string motivos = string.Join("; ", modulo?.motivos ?? new List<string>() { "Desconhecido" });
|
||||
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 620,
|
||||
Fonte = "ModuloCritico",
|
||||
Titulo = "MÓDULO MANDATÓRIO NÃO OPERACIONAL",
|
||||
Descricao = $"{nomeModulo}: módulo mandatório em estado '{statusTexto}': {motivos}",
|
||||
StatusVisual = StatusModulo.Falha,
|
||||
Modulo = modulo?.modulo
|
||||
});
|
||||
}
|
||||
|
||||
// Caso 2: condições operacionais severas
|
||||
if (temCondicaoSevera)
|
||||
{
|
||||
var descricoesCriticas = modulo?.condicoes_operacionais?
|
||||
|
|
@ -515,7 +550,7 @@ namespace OperationControl.ViewModels
|
|||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 600,
|
||||
Prioridade = 610,
|
||||
Fonte = "ModuloCritico",
|
||||
Titulo = "CONDIÇÕES OPERACIONAIS CRÍTICAS",
|
||||
Descricao = $"{nomeModulo}: {desc}",
|
||||
|
|
@ -525,18 +560,19 @@ namespace OperationControl.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
// Caso 2: módulo mandatório não operante
|
||||
if (moduloMandatorioNaoOperante)
|
||||
// Caso 3: módulo mandatório em alerta
|
||||
if (moduloMandatorioAlerta)
|
||||
{
|
||||
var statusTexto = (modulo?.status ?? StatusModulo.Desconectado).ToString();
|
||||
string motivos = string.Join("; ", modulo?.motivos ?? new List<string>() { "Desconhecido" });
|
||||
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 610,
|
||||
Prioridade = 600,
|
||||
Fonte = "ModuloCritico",
|
||||
Titulo = "MÓDULO MANDATÓRIO NÃO OPERACIONAL",
|
||||
Descricao = $"{nomeModulo}: módulo mandatório em estado '{statusTexto}'",
|
||||
StatusVisual = StatusModulo.Falha,
|
||||
Titulo = "MÓDULO MANDATÓRIO EM ALERTA",
|
||||
Descricao = $"{nomeModulo}: módulo mandatório em estado '{statusTexto}': {motivos}",
|
||||
StatusVisual = StatusModulo.Alerta,
|
||||
Modulo = modulo?.modulo
|
||||
});
|
||||
}
|
||||
|
|
@ -565,6 +601,20 @@ namespace OperationControl.ViewModels
|
|||
.ThenBy(x => x.Fonte)
|
||||
.ToList();
|
||||
|
||||
if (!eventosOrdenados.Any())
|
||||
{
|
||||
eventosOrdenados.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 0,
|
||||
Fonte = "Normal",
|
||||
Titulo = "ROVER OPERANDO NORMALMENTE",
|
||||
Descricao = "Trajetória, controle e operação em condição normal.",
|
||||
StatusVisual = obj.StatusRover == StatusModulo.Desconectado
|
||||
? StatusModulo.Desconectado
|
||||
: StatusModulo.Operante
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 7) Monta visual final
|
||||
// ============================
|
||||
|
|
@ -627,6 +677,8 @@ namespace OperationControl.ViewModels
|
|||
resumo = (obj.Operacao?.Status ?? StatusOperacao.NaoIniciado).ToString();
|
||||
}
|
||||
|
||||
_viewOperacaoCenter?.Historico?._vm?.CompararERegistrarMudancasEventos(rover.RoverId, eventosOrdenados);
|
||||
|
||||
// Segurança extra: evita linha vazia
|
||||
if (string.IsNullOrWhiteSpace(linha2))
|
||||
linha2 = "Sem detalhes adicionais.";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,382 @@
|
|||
<UserControl x:Class="OperationControl.Views.Operacao.Monitoramento.HistoricoView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:OperationControl.Views.Operacao.Monitoramento"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="900"
|
||||
d:DesignWidth="1600">
|
||||
|
||||
<UserControl.Resources>
|
||||
|
||||
<!-- Campo base escuro -->
|
||||
<Style x:Key="DarkInputTextBoxStyle" TargetType="TextBox">
|
||||
<Setter Property="Height" Value="36"/>
|
||||
<Setter Property="Padding" Value="10,6"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="Background" Value="#111315"/>
|
||||
<Setter Property="BorderBrush" Value="#323842"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CaretBrush" Value="White"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="TextBox">
|
||||
<Border x:Name="Bd"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="10">
|
||||
<ScrollViewer x:Name="PART_ContentHost"
|
||||
Margin="0"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsKeyboardFocused" Value="True">
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="#4C89FF"/>
|
||||
<Setter TargetName="Bd" Property="Background" Value="#14181D"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="#46505C"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="Bd" Property="Opacity" Value="0.65"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- ComboBox escuro -->
|
||||
<Style x:Key="DarkComboBoxStyle" TargetType="ComboBox">
|
||||
<Setter Property="Height" Value="36"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="Background" Value="#111315"/>
|
||||
<Setter Property="BorderBrush" Value="#323842"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="Padding" Value="10,6"/>
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ComboBox">
|
||||
<Grid>
|
||||
<Border x:Name="Bd"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="10"/>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="36"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- texto selecionado -->
|
||||
<ContentPresenter Grid.Column="0"
|
||||
Margin="12,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
RecognizesAccessKey="True"
|
||||
Content="{TemplateBinding SelectionBoxItem}"
|
||||
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"/>
|
||||
|
||||
<!-- seta -->
|
||||
<Border Grid.Column="1"
|
||||
Background="Transparent">
|
||||
<Path Width="10"
|
||||
Height="6"
|
||||
Stretch="Fill"
|
||||
Fill="#C8D0DA"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Data="M 0 0 L 10 0 L 5 6 Z"/>
|
||||
</Border>
|
||||
|
||||
<!-- área clicável -->
|
||||
<ToggleButton Grid.ColumnSpan="2"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Focusable="False"
|
||||
ClickMode="Press"
|
||||
IsChecked="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
|
||||
<ToggleButton.Template>
|
||||
<ControlTemplate TargetType="ToggleButton">
|
||||
<Border Background="Transparent"/>
|
||||
</ControlTemplate>
|
||||
</ToggleButton.Template>
|
||||
</ToggleButton>
|
||||
</Grid>
|
||||
|
||||
<Popup x:Name="Popup"
|
||||
Placement="Bottom"
|
||||
AllowsTransparency="True"
|
||||
Focusable="False"
|
||||
StaysOpen="False"
|
||||
IsOpen="{TemplateBinding IsDropDownOpen}"
|
||||
PopupAnimation="Fade">
|
||||
<Border Margin="0,4,0,0"
|
||||
Background="#1A1D21"
|
||||
BorderBrush="#323842"
|
||||
BorderThickness="1"
|
||||
CornerRadius="10"
|
||||
MinWidth="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<ScrollViewer MaxHeight="320"
|
||||
CanContentScroll="True">
|
||||
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained"/>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsKeyboardFocusWithin" Value="True">
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="#4C89FF"/>
|
||||
<Setter TargetName="Bd" Property="Background" Value="#14181D"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="#46505C"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="Bd" Property="Opacity" Value="0.65"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="ItemContainerStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="ComboBoxItem">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Padding" Value="10,6"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ComboBoxItem">
|
||||
<Border x:Name="ItemBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsHighlighted" Value="True">
|
||||
<Setter TargetName="ItemBorder" Property="Background" Value="#2A313A"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="ItemBorder" Property="Background" Value="#314256"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Botão secundário, caso use depois -->
|
||||
<Style x:Key="DarkSmallButtonStyle" TargetType="Button">
|
||||
<Setter Property="Height" Value="36"/>
|
||||
<Setter Property="Padding" Value="14,6"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="Background" Value="#20252B"/>
|
||||
<Setter Property="BorderBrush" Value="#323842"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="Bd"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="10">
|
||||
<ContentPresenter HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Bd" Property="Background" Value="#2A3138"/>
|
||||
<Setter TargetName="Bd" Property="BorderBrush" Value="#46505C"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="Bd" Property="Background" Value="#151A1F"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="Bd" Property="Opacity" Value="0.65"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="#111315">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- CABEÇALHO -->
|
||||
<StackPanel Grid.Row="0" Margin="16,16,16,0">
|
||||
<Border Padding="18" CornerRadius="14" Background="#1A1D21" BorderBrush="#2A2E35" BorderThickness="1">
|
||||
<StackPanel>
|
||||
<DockPanel LastChildFill="False">
|
||||
<StackPanel DockPanel.Dock="Left">
|
||||
<TextBlock Text="Histórico operacional" FontSize="22" FontWeight="SemiBold" Foreground="White"/>
|
||||
<TextBlock Margin="0,6,0,0" FontSize="13" Foreground="#B8C0CC">
|
||||
<Run Text="Exibindo "/>
|
||||
<Run Text="{Binding QuantidadeEventosFiltrados, Mode=OneWay}"/>
|
||||
<Run Text=" eventos filtrados de "/>
|
||||
<Run Text="{Binding QuantidadeEventos, Mode=OneWay}"/>
|
||||
<Run Text=" eventos"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
|
||||
<StackPanel Margin="0,16,0,0">
|
||||
<TextBlock Text="Busca e filtros" Margin="2,0,0,10" FontSize="12" Foreground="#8F99A5"/>
|
||||
|
||||
<WrapPanel>
|
||||
<TextBox Width="260" Margin="0,0,10,10" Text="{Binding TextoBusca, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource DarkInputTextBoxStyle}" ToolTip="Buscar por título, descrição, fonte, módulo..." />
|
||||
|
||||
<ComboBox Width="150" Margin="0,0,10,10" ItemsSource="{Binding TiposTransicaoDisponiveis}" SelectedItem="{Binding TipoTransicaoSelecionado}" Style="{StaticResource DarkComboBoxStyle}" />
|
||||
|
||||
<ComboBox Width="150" Margin="0,0,10,10" ItemsSource="{Binding StatusDisponiveis}" SelectedItem="{Binding StatusSelecionado}" Style="{StaticResource DarkComboBoxStyle}" />
|
||||
|
||||
<ComboBox Width="170" Margin="0,0,10,10" ItemsSource="{Binding FontesDisponiveis}" SelectedItem="{Binding FonteSelecionada}" Style="{StaticResource DarkComboBoxStyle}" />
|
||||
|
||||
<ComboBox Width="160" Margin="0,0,10,10" ItemsSource="{Binding OrdenacoesDisponiveis}" SelectedItem="{Binding OrdenacaoSelecionada}" Style="{StaticResource DarkComboBoxStyle}" />
|
||||
|
||||
<Border Background="#111315" BorderBrush="#323842" BorderThickness="1" CornerRadius="10" Height="36" Padding="12,6" Margin="0,0,10,10">
|
||||
<TextBlock VerticalAlignment="Center" Foreground="#B8C0CC" FontSize="12" Text="{Binding RoverIdSelecionado, StringFormat=Rover: {0}}" />
|
||||
</Border>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- LISTA -->
|
||||
<Border Grid.Row="1"
|
||||
Margin="16,0,16,16"
|
||||
Padding="8"
|
||||
CornerRadius="14"
|
||||
Background="#16191D"
|
||||
BorderBrush="#2A2E35"
|
||||
BorderThickness="1">
|
||||
|
||||
<ListBox ItemsSource="{Binding EventosView}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
VirtualizingPanel.IsVirtualizing="True"
|
||||
VirtualizingPanel.VirtualizationMode="Recycling">
|
||||
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Focusable" Value="False"/>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="#1D2126"
|
||||
CornerRadius="12"
|
||||
BorderBrush="#2B3138"
|
||||
BorderThickness="1"
|
||||
Padding="0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="6"/>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="110"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- barra lateral -->
|
||||
<Border Grid.Column="0"
|
||||
Background="{Binding CorAccent}"
|
||||
CornerRadius="12,0,0,12"/>
|
||||
|
||||
<!-- hora -->
|
||||
<StackPanel Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="16,14,10,14">
|
||||
<TextBlock Text="{Binding Hora}"
|
||||
FontSize="20"
|
||||
FontWeight="Bold"
|
||||
Foreground="White"
|
||||
HorizontalAlignment="Left"/>
|
||||
<TextBlock Text="{Binding DataHoraCompleta}"
|
||||
Margin="0,4,0,0"
|
||||
FontSize="11"
|
||||
Foreground="#9DA7B3"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- conteúdo -->
|
||||
<StackPanel Grid.Column="2"
|
||||
Margin="8,14,16,14">
|
||||
<TextBlock Text="{Binding Titulo}"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="White"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Text="{Binding Descricao}"
|
||||
Margin="0,8,0,0"
|
||||
FontSize="13"
|
||||
Foreground="#D0D7E2"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Text="{Binding Subtitulo}"
|
||||
Margin="0,10,0,0"
|
||||
FontSize="12"
|
||||
Foreground="#8F99A5"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- badge -->
|
||||
<StackPanel Grid.Column="3"
|
||||
Margin="0,14,14,14"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Right">
|
||||
<Border Background="{Binding CorBadge}"
|
||||
CornerRadius="10"
|
||||
Padding="10,4">
|
||||
<TextBlock Text="{Binding TipoTransicao}"
|
||||
Foreground="White"
|
||||
FontSize="11"
|
||||
FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
|
||||
|
||||
namespace OperationControl.Views.Operacao.Monitoramento
|
||||
{
|
||||
/// <summary>
|
||||
/// Interação lógica para HistoricoView.xam
|
||||
/// </summary>
|
||||
public partial class HistoricoView : System.Windows.Controls.UserControl
|
||||
{
|
||||
public HistoricoViewModel _vm;
|
||||
|
||||
public HistoricoView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_vm = new HistoricoViewModel();
|
||||
DataContext = _vm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,5 +33,10 @@
|
|||
<views:MonitoramentoView x:Name="areaMonitor"/>
|
||||
</Grid>
|
||||
|
||||
<!-- HSITORICO -->
|
||||
<Grid Visibility="{Binding ExibirHistorico, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<views:HistoricoView x:Name="areaHistorico"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
@ -13,6 +13,7 @@ namespace OperationControl.Views.Operacao
|
|||
public MapViewControl Mapa => _vm?.ConteudoAtual == OperacaoCenterConteudo.Mapa ? areaMapa : _vm?.ConteudoAtual == OperacaoCenterConteudo.Monitoramento ? Monitoramento?.MapaMonitoramento : null;
|
||||
public MonitoramentoView Monitoramento => areaMonitor;
|
||||
public DiagnosticoView Diagnostico => areaDiagnostico;
|
||||
public HistoricoView Historico => areaHistorico;
|
||||
|
||||
public OperacaoCenterView()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@
|
|||
<Button Content="Controle ▶" Style="{StaticResource MenuButtonStyle}" Command="{Binding SelecionarSecaoCommand}" CommandParameter="Controle"/>
|
||||
|
||||
<Button Content="Resumo ▶" Style="{StaticResource MenuButtonStyle}" Command="{Binding SelecionarSecaoCommand}" CommandParameter="Resumo"/>
|
||||
|
||||
<Button Content="Histórico" Style="{StaticResource MenuButtonStyle}" Command="{Binding SelecionarSecaoCommand}" CommandParameter="Historico"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- RESUMO -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue