Внёс мелкие правки и фиксы

This commit is contained in:
2025-11-21 10:31:26 +03:00
parent c2c8c8799f
commit 58838614a5
13 changed files with 423 additions and 99 deletions

View File

@@ -23,10 +23,10 @@
<a class="nav-link" href="{% url 'mainapp:objitem_list' %}">Точки</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'mainapp:transponder_list' %}">Транспондеры</a>
<a class="nav-link" href="{% url 'mainapp:satellite_list' %}">Спутники</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'mainapp:satellite_list' %}">Спутники</a>
<a class="nav-link" href="{% url 'mainapp:transponder_list' %}">Транспондеры</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'lyngsatapp:lyngsat_list' %}">Справочные данные</a>

View File

@@ -107,10 +107,17 @@
<small class="form-text text-muted">Удерживайте Ctrl для выбора нескольких</small>
</div>
<!-- Принадлежность объекта (заглушка) -->
<!-- Принадлежность объекта -->
<div class="col-md-3 mb-3">
<label for="{{ form.object_ownership.id_for_label }}" class="form-label">{{ form.object_ownership.label }} (не работает)</label>
<label for="{{ form.object_ownership.id_for_label }}" class="form-label">{{ form.object_ownership.label }}</label>
<div class="d-flex justify-content-between mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('object_ownership', true)">Выбрать</button>
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('object_ownership', false)">Снять</button>
</div>
{{ form.object_ownership }}
<small class="form-text text-muted">Удерживайте Ctrl для выбора нескольких</small>
</div>
</div>
@@ -231,6 +238,7 @@
<tr>
<th style="min-width: 80px;">ID объекта</th>
<th style="min-width: 120px;">Тип объекта</th>
<th style="min-width: 150px;">Принадлежность объекта</th>
<th class="text-center" style="min-width: 100px;">Кол-во точек</th>
<th style="min-width: 120px;">Имя точки</th>
<th style="min-width: 150px;">Спутник</th>
@@ -261,6 +269,24 @@
<td rowspan="{{ source_data.objitems_data|length }}" class="source-type-cell">{{ source_data.source.info.name|default:"-" }}</td>
{% endif %}
<!-- Принадлежность объекта (только для первой строки источника) -->
{% if forloop.first %}
<td rowspan="{{ source_data.objitems_data|length }}" class="source-ownership-cell">
{% if source_data.source.ownership %}
{% if source_data.source.ownership.name == "ТВ" and source_data.has_lyngsat %}
<a href="#" class="text-primary text-decoration-none"
onclick="showLyngsatModal({{ source_data.lyngsat_id }}); return false;">
<i class="bi bi-tv"></i> {{ source_data.source.ownership.name }}
</a>
{% else %}
{{ source_data.source.ownership.name }}
{% endif %}
{% else %}
-
{% endif %}
</td>
{% endif %}
<!-- Количество точек (только для первой строки источника) -->
{% if forloop.first %}
<td rowspan="{{ source_data.objitems_data|length }}" class="text-center source-count-cell" data-initial-count="{{ source_data.objitems_data|length }}">{{ source_data.objitems_data|length }}</td>
@@ -539,6 +565,55 @@ function selectAllOptions(selectName, selectAll) {
document.addEventListener('DOMContentLoaded', function() {
updateCounter();
});
// Функция для показа модального окна LyngSat
function showLyngsatModal(lyngsatId) {
const modal = new bootstrap.Modal(document.getElementById('lyngsatModal'));
modal.show();
const modalBody = document.getElementById('lyngsatModalBody');
modalBody.innerHTML = '<div class="text-center py-4"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Загрузка...</span></div></div>';
fetch('/api/lyngsat/' + lyngsatId + '/')
.then(response => {
if (!response.ok) {
throw new Error('Ошибка загрузки данных');
}
return response.json();
})
.then(data => {
let html = '<div class="container-fluid"><div class="row g-3">' +
'<div class="col-md-6"><div class="card h-100">' +
'<div class="card-header bg-light"><strong><i class="bi bi-info-circle"></i> Основная информация</strong></div>' +
'<div class="card-body"><table class="table table-sm table-borderless mb-0"><tbody>' +
'<tr><td class="text-muted" style="width: 40%;">Спутник:</td><td><strong>' + data.satellite + '</strong></td></tr>' +
'<tr><td class="text-muted">Частота:</td><td><strong>' + data.frequency + ' МГц</strong></td></tr>' +
'<tr><td class="text-muted">Поляризация:</td><td><span class="badge bg-info">' + data.polarization + '</span></td></tr>' +
'<tr><td class="text-muted">Канал:</td><td>' + data.channel_info + '</td></tr>' +
'</tbody></table></div></div></div>' +
'<div class="col-md-6"><div class="card h-100">' +
'<div class="card-header bg-light"><strong><i class="bi bi-gear"></i> Технические параметры</strong></div>' +
'<div class="card-body"><table class="table table-sm table-borderless mb-0"><tbody>' +
'<tr><td class="text-muted" style="width: 40%;">Модуляция:</td><td><span class="badge bg-secondary">' + data.modulation + '</span></td></tr>' +
'<tr><td class="text-muted">Стандарт:</td><td><span class="badge bg-secondary">' + data.standard + '</span></td></tr>' +
'<tr><td class="text-muted">Сим. скорость:</td><td><strong>' + data.sym_velocity + ' БОД</strong></td></tr>' +
'<tr><td class="text-muted">FEC:</td><td>' + data.fec + '</td></tr>' +
'</tbody></table></div></div></div>' +
'<div class="col-12"><div class="card">' +
'<div class="card-header bg-light"><strong><i class="bi bi-clock-history"></i> Дополнительная информация</strong></div>' +
'<div class="card-body"><div class="row">' +
'<div class="col-md-6"><p class="mb-2"><span class="text-muted">Последнее обновление:</span><br><strong>' + data.last_update + '</strong></p></div>' +
'<div class="col-md-6">' + (data.url ? '<p class="mb-2"><span class="text-muted">Ссылка на объект:</span><br>' +
'<a href="' + data.url + '" target="_blank" class="btn btn-sm btn-outline-primary">' +
'<i class="bi bi-link-45deg"></i> Открыть на LyngSat</a></p>' : '') +
'</div></div></div></div></div></div></div>';
modalBody.innerHTML = html;
})
.catch(error => {
modalBody.innerHTML = '<div class="alert alert-danger" role="alert">' +
'<i class="bi bi-exclamation-triangle"></i> ' + error.message + '</div>';
});
}
</script>
<style>
@@ -569,4 +644,29 @@ document.addEventListener('DOMContentLoaded', function() {
z-index: 10;
}
</style>
<!-- LyngSat Data Modal -->
<div class="modal fade" id="lyngsatModal" tabindex="-1" aria-labelledby="lyngsatModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="lyngsatModalLabel">
<i class="bi bi-tv"></i> Данные объекта LyngSat
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Закрыть"></button>
</div>
<div class="modal-body" id="lyngsatModalBody">
<div class="text-center py-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Загрузка...</span>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Закрыть</button>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -200,10 +200,10 @@
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">
<i class="bi bi-save"></i> Сохранить
Сохранить
</button>
<a href="{% url 'mainapp:satellite_list' %}" class="btn btn-secondary">
<i class="bi bi-x-circle"></i> Отмена
Отмена
</a>
</div>
</form>
@@ -214,7 +214,7 @@
{% if action == 'update' and transponders %}
<!-- Frequency Plan Visualization -->
<div class="row mt-4">
<!-- <div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-body">
@@ -256,7 +256,7 @@
</div>
</div>
</div>
</div>
</div> -->
<div class="transponder-tooltip" id="transponderTooltip"></div>
{% endif %}

View File

@@ -206,6 +206,17 @@
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="id_ownership" class="form-label">{{ form.ownership.label }}:</label>
{{ form.ownership }}
{% if form.ownership.errors %}
<div class="invalid-feedback d-block">
{{ form.ownership.errors }}
</div>
{% endif %}
</div>
</div>
</div>
</div>
@@ -227,7 +238,7 @@
<!-- Координаты ГЛ -->
<div class="coord-group">
<div class="coord-group-header">Координаты ГЛ (усреднённые)</div>
<div class="coord-group-header">Координаты ГЛ</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
@@ -581,9 +592,8 @@
document.getElementById('save-btn').disabled = false;
document.getElementById('cancel-btn').disabled = false;
// Включаем drag для всех маркеров
Object.values(markers).forEach(m => {
if (m.marker.options.opacity !== 0) {
Object.entries(markers).forEach(([key, m]) => {
if (key !== 'average' && m.marker.options.opacity !== 0) {
m.marker.enableEditing();
}
});

View File

@@ -227,23 +227,6 @@
</div>
</div>
<!-- LyngSat Filter -->
<div class="mb-2">
<label class="form-label">ТВ или нет:</label>
<div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="has_lyngsat" id="has_lyngsat_1"
value="1" {% if has_lyngsat == '1' %}checked{% endif %}>
<label class="form-check-label" for="has_lyngsat_1">Есть</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="has_lyngsat" id="has_lyngsat_0"
value="0" {% if has_lyngsat == '0' %}checked{% endif %}>
<label class="form-check-label" for="has_lyngsat_0">Нет</label>
</div>
</div>
</div>
<!-- ObjectInfo Filter -->
<div class="mb-2">
<label class="form-label">Тип объекта:</label>
@@ -262,6 +245,24 @@
</select>
</div>
<!-- ObjectOwnership Filter -->
<div class="mb-2">
<label class="form-label">Принадлежность объекта:</label>
<div class="d-flex justify-content-between mb-1">
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('ownership_id', true)">Выбрать</button>
<button type="button" class="btn btn-sm btn-outline-secondary"
onclick="selectAllOptions('ownership_id', false)">Снять</button>
</div>
<select name="ownership_id" class="form-select form-select-sm mb-2" multiple size="4">
{% for ownership in object_ownerships %}
<option value="{{ ownership.id }}" {% if ownership.id in selected_ownership %}selected{% endif %}>
{{ ownership.name }}
</option>
{% endfor %}
</select>
</div>
<!-- Point Count Filter -->
<div class="mb-2">
<label class="form-label">Количество точек:</label>
@@ -435,6 +436,7 @@
<th scope="col" style="min-width: 150px;">Имя</th>
<th scope="col" style="min-width: 120px;">Спутник</th>
<th scope="col" style="min-width: 120px;">Тип объекта</th>
<th scope="col" style="min-width: 150px;">Принадлежность объекта</th>
<th scope="col" style="min-width: 150px;">Координаты ГЛ</th>
<th scope="col" class="text-center" style="min-width: 100px;">
{% include 'mainapp/components/_sort_header.html' with field='objitem_count' label='Кол-во ГЛ(точек)' current_sort=sort %}
@@ -443,7 +445,6 @@
<th scope="col" style="min-width: 150px;">Координаты визуального наблюдения</th>
<th scope="col" style="min-width: 150px;">Координаты справочные</th>
<th scope="col" style="min-width: 180px;">Наличие сигнала</th>
<th scope="col" class="text-center" style="min-width: 80px;">ТВ или нет</th>
<th scope="col" style="min-width: 120px;">
{% include 'mainapp/components/_sort_header.html' with field='created_at' label='Создано' current_sort=sort %}
</th>
@@ -473,6 +474,16 @@
{% endif %}
</td>
<td>{{ source.info }}</td>
<td>
{% if source.ownership == "ТВ" and source.has_lyngsat %}
<a href="#" class="text-primary text-decoration-none"
onclick="showLyngsatModal({{ source.lyngsat_id }}); return false;">
<i class="bi bi-tv"></i> {{ source.ownership }}
</a>
{% else %}
{{ source.ownership }}
{% endif %}
</td>
<td>{{ source.coords_average }}</td>
<td class="text-center">{{ source.objitem_count }}</td>
<td>{{ source.coords_kupsat }}</td>
@@ -501,16 +512,6 @@
<span class="text-muted">-</span>
{% endif %}
</td>
<td class="text-center">
{% if source.has_lyngsat %}
<a href="#" class="text-primary text-decoration-none"
onclick="showLyngsatModal({{ source.lyngsat_id }}); return false;">
<i class="bi bi-tv"></i> ТВ
</a>
{% else %}
-
{% endif %}
</td>
<td>{{ source.created_at|date:"d.m.Y H:i" }}</td>
<td>{{ source.updated_at|date:"d.m.Y H:i" }}</td>
@@ -1091,7 +1092,6 @@ document.addEventListener('DOMContentLoaded', function() {
setupRadioLikeCheckboxes('has_coords_kupsat');
setupRadioLikeCheckboxes('has_coords_valid');
setupRadioLikeCheckboxes('has_coords_reference');
setupRadioLikeCheckboxes('has_lyngsat');
setupRadioLikeCheckboxes('has_signal_mark');
// Update filter counter on page load