Files
dbstorage/dbapp/mainapp/templates/mainapp/objitem_detail.html

473 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends 'mainapp/base.html' %}
{% load static %}
{% load static leaflet_tags %}
{% load l10n %}
{% block title %}Просмотр объекта: {{ object.name }}{% endblock %}
{% block extra_css %}
<style>
.form-section { margin-bottom: 2rem; border: 1px solid #dee2e6; border-radius: 0.25rem; padding: 1rem; }
.form-section-header { border-bottom: 1px solid #dee2e6; padding-bottom: 0.5rem; margin-bottom: 1rem; }
.btn-action { margin-right: 0.5rem; }
.readonly-field { background-color: #f8f9fa; padding: 0.375rem 0.75rem; border: 1px solid #ced4da; border-radius: 0.25rem; }
.coord-group { border: 1px solid #dee2e6; padding: 0.75rem; border-radius: 0.25rem; margin-bottom: 1rem; }
.coord-group-header { font-weight: bold; margin-bottom: 0.5rem; }
.form-check-input { margin-top: 0.25rem; }
.datetime-group { display: flex; gap: 1rem; }
.datetime-group > div { flex: 1; }
#map { height: 500px; width: 100%; margin-bottom: 1rem; }
.map-container { margin-bottom: 1rem; }
.coord-sync-group { border: 1px solid #dee2e6; padding: 0.75rem; border-radius: 0.25rem; }
.map-controls {
display: flex;
gap: 10px;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.map-control-btn {
padding: 0.375rem 0.75rem;
border: 1px solid #ced4da;
background-color: #f8f9fa;
border-radius: 0.25rem;
cursor: pointer;
}
.map-control-btn.active {
background-color: #e9ecef;
border-color: #dee2e6;
}
.map-control-btn.edit {
background-color: #fff3cd;
border-color: #ffeeba;
}
.map-control-btn.save {
background-color: #d1ecf1;
border-color: #bee5eb;
}
.map-control-btn.cancel {
background-color: #f8d7da;
border-color: #f5c6cb;
}
.leaflet-marker-icon {
filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.3));
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid px-3">
<div class="row mb-3">
<div class="col-12 d-flex justify-content-between align-items-center">
<h2>Просмотр объекта: {{ object.name }}</h2>
<div>
<a href="{% url 'mainapp:objitem_list' %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-secondary btn-action">Назад</a>
</div>
</div>
</div>
<!-- Основная информация -->
<div class="form-section">
<div class="form-section-header">
<h4>Основная информация</h4>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Название:</label>
<div class="readonly-field">{{ object.name|default:"-" }}</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Дата создания:</label>
<div class="readonly-field">
{% if object.created_at %}{{ object.created_at|date:"d.m.Y H:i" }}{% else %}-{% endif %}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Создан пользователем:</label>
<div class="readonly-field">
{% if object.created_by %}{{ object.created_by }}{% else %}-{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Дата последнего изменения:</label>
<div class="readonly-field">
{% if object.updated_at %}{{ object.updated_at|date:"d.m.Y H:i" }}{% else %}-{% endif %}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Изменен пользователем:</label>
<div class="readonly-field">
{% if object.updated_by %}{{ object.updated_by }}{% else %}-{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- ВЧ загрузка -->
<div class="form-section">
<div class="form-section-header">
<h4>ВЧ загрузка</h4>
</div>
{% if object.parameter_obj %}
<div class="row">
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Спутник:</label>
<div class="readonly-field">{{ object.parameter_obj.id_satellite.name|default:"-" }}</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Частота (МГц):</label>
<div class="readonly-field">{{ object.parameter_obj.frequency|default:"-" }}</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Полоса (МГц):</label>
<div class="readonly-field">{{ object.parameter_obj.freq_range|default:"-" }}</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Поляризация:</label>
<div class="readonly-field">{{ object.parameter_obj.polarization.name|default:"-" }}</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Символьная скорость:</label>
<div class="readonly-field">{{ object.parameter_obj.bod_velocity|default:"-" }}</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Модуляция:</label>
<div class="readonly-field">{{ object.parameter_obj.modulation.name|default:"-" }}</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">ОСШ:</label>
<div class="readonly-field">{{ object.parameter_obj.snr|default:"-" }}</div>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<label class="form-label">Стандарт:</label>
<div class="readonly-field">{{ object.parameter_obj.standard.name|default:"-" }}</div>
</div>
</div>
</div>
{% else %}
<div class="mb-3">
<p>Нет данных о ВЧ загрузке</p>
</div>
{% endif %}
</div>
<!-- Блок с картой -->
<div class="form-section">
<div class="form-section-header">
<h4>Карта</h4>
</div>
<div class="map-container">
<div id="map"></div>
</div>
</div>
<!-- Геоданные -->
<div class="form-section">
<div class="form-section-header">
<h4>Геоданные</h4>
</div>
{% if object.geo_obj %}
<!-- Координаты геолокации -->
<div class="coord-sync-group">
<div class="coord-group-header">Координаты геолокации</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Широта:</label>
<div class="readonly-field">
{% if object.geo_obj.coords %}{{ object.geo_obj.coords.y|floatformat:6 }}{% else %}-{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<label class="form-label">Долгота:</label>
<div class="readonly-field">
{% if object.geo_obj.coords %}{{ object.geo_obj.coords.x|floatformat:6 }}{% else %}-{% endif %}
</div>
</div>
</div>
</div>
<!-- Координаты Кубсата -->
<div class="coord-group">
<div class="coord-group-header">Координаты Кубсата</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Долгота:</label>
<div class="readonly-field">
{% if object.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.x|floatformat:6 }}{% else %}-{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Широта:</label>
<div class="readonly-field">
{% if object.geo_obj.coords_kupsat %}{{ object.geo_obj.coords_kupsat.y|floatformat:6 }}{% else %}-{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- Координаты оперативников -->
<div class="coord-group">
<div class="coord-group-header">Координаты оперативников</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Долгота:</label>
<div class="readonly-field">
{% if object.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.x|floatformat:6 }}{% else %}-{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Широта:</label>
<div class="readonly-field">
{% if object.geo_obj.coords_valid %}{{ object.geo_obj.coords_valid.y|floatformat:6 }}{% else %}-{% endif %}
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Местоположение:</label>
<div class="readonly-field">{{ object.geo_obj.location|default:"-" }}</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Комментарий:</label>
<div class="readonly-field">{{ object.geo_obj.comment|default:"-" }}</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Дата и время:</label>
<div class="readonly-field">
{% if object.geo_obj.timestamp %}{{ object.geo_obj.timestamp|date:"d.m.Y H:i" }}{% else %}-{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-check-label">Усредненное значение:</label>
<div class="readonly-field">
{% if object.geo_obj.is_average %}Да{% else %}Нет{% endif %}
</div>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Расстояние гео-кубсат, км:</label>
<div class="readonly-field">
{% if object.geo_obj.distance_coords_kup is not None %}
{{ object.geo_obj.distance_coords_kup|floatformat:2 }}
{% else %}
-
{% endif %}
</div>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Расстояние гео-опер, км:</label>
<div class="readonly-field">
{% if object.geo_obj.distance_coords_valid is not None %}
{{ object.geo_obj.distance_coords_valid|floatformat:2 }}
{% else %}
-
{% endif %}
</div>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label class="form-label">Расстояние кубсат-опер, км:</label>
<div class="readonly-field">
{% if object.geo_obj.distance_kup_valid is not None %}
{{ object.geo_obj.distance_kup_valid|floatformat:2 }}
{% else %}
-
{% endif %}
</div>
</div>
</div>
</div>
{% else %}
<p>Нет данных о геолокации</p>
{% endif %}
</div>
</div>
<div class="d-flex justify-content-end mt-4">
{% if user.customuser.role == 'admin' or user.customuser.role == 'moderator' %}
<a href="{% url 'mainapp:objitem_update' object.id %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-primary btn-action">Редактировать</a>
{% endif %}
<a href="{% url 'mainapp:objitem_list' %}{% if request.GET.urlencode %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-secondary btn-action">Назад</a>
</div>
</div>
{% endblock %}
{% block extra_js %}
{{ block.super }}
<!-- Подключаем Leaflet и его плагины -->
{% leaflet_js %}
{% leaflet_css %}
<script src="{% static 'leaflet-markers/js/leaflet-color-markers.js' %}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Инициализация карты
const map = L.map('map').setView([55.75, 37.62], 5);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Определяем цвета для маркеров
const colors = {
geo: 'blue',
kupsat: 'red',
valid: 'green'
};
// Функция для создания иконки маркера
function createMarkerIcon(color) {
return L.icon({
iconUrl: '{% static "leaflet-markers/img/marker-icon-" %}' + color + '.png',
shadowUrl: `{% static 'leaflet-markers/img/marker-shadow.png' %}`,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
}
// Маркеры
const markers = {};
function createMarker(position, color, name) {
const marker = L.marker(position, {
draggable: false,
icon: createMarkerIcon(color),
title: name
}).addTo(map);
marker.bindPopup(name);
return marker;
}
// Получаем координаты из данных объекта
{% if object.geo_obj and object.geo_obj.coords %}
const geoLat = {{ object.geo_obj.coords.y|unlocalize }};
const geoLng = {{ object.geo_obj.coords.x|unlocalize }};
{% else %}
const geoLat = 55.75;
const geoLng = 37.62;
{% endif %}
{% if object.geo_obj and object.geo_obj.coords_kupsat %}
const kupsatLat = {{ object.geo_obj.coords_kupsat.y|unlocalize }};
const kupsatLng = {{ object.geo_obj.coords_kupsat.x|unlocalize }};
{% else %}
const kupsatLat = 55.75;
const kupsatLng = 37.61;
{% endif %}
{% if object.geo_obj and object.geo_obj.coords_valid %}
const validLat = {{ object.geo_obj.coords_valid.y|unlocalize }};
const validLng = {{ object.geo_obj.coords_valid.x|unlocalize }};
{% else %}
const validLat = 55.75;
const validLng = 37.63;
{% endif %}
// Создаем маркеры
markers.geo = createMarker(
[geoLat, geoLng],
colors.geo,
'Геолокация'
);
markers.kupsat = createMarker(
[kupsatLat, kupsatLng],
colors.kupsat,
'Кубсат'
);
markers.valid = createMarker(
[validLat, validLng],
colors.valid,
'Оперативник'
);
// Центрируем карту на первом маркере
if (map.hasLayer(markers.geo)) {
map.setView(markers.geo.getLatLng(), 10);
}
// Легенда
const legend = L.control({ position: 'bottomright' });
legend.onAdd = function() {
const div = L.DomUtil.create('div', 'info legend');
div.style.fontSize = '14px';
div.style.backgroundColor = 'white';
div.style.padding = '10px';
div.style.borderRadius = '4px';
div.style.boxShadow = '0 0 10px rgba(0,0,0,0.2)';
div.innerHTML = `
<h5>Легенда</h5>
<div><span style="color: blue; font-weight: bold;">•</span> Геолокация</div>
<div><span style="color: red; font-weight: bold;">•</span> Кубсат</div>
<div><span style="color: green; font-weight: bold;">•</span> Оперативники</div>
`;
return div;
};
legend.addTo(map);
});
</script>
{% endblock %}