Поправил кубсат и добавил библиотеку luxon

This commit is contained in:
2025-12-11 11:27:01 +03:00
parent f79efd88e5
commit f5875e5b87
4 changed files with 86 additions and 22 deletions

View File

@@ -218,7 +218,7 @@ const requestsTable = new Tabulator("#requestsTable", {
selectableRangeMode: "click", selectableRangeMode: "click",
pagination: true, pagination: true,
paginationSize: 50, paginationSize: 50,
paginationSizeSelector: [25, 50, 100, 200], paginationSizeSelector: [50, 200, 500, true],
paginationCounter: "rows", paginationCounter: "rows",
columns: [ columns: [
{ {
@@ -235,21 +235,48 @@ const requestsTable = new Tabulator("#requestsTable", {
{title: "Ист.", field: "source_id", width: 55, formatter: sourceFormatter}, {title: "Ист.", field: "source_id", width: 55, formatter: sourceFormatter},
{title: "Спутник", field: "satellite_name", width: 100}, {title: "Спутник", field: "satellite_name", width: 100},
{title: "Статус", field: "status", width: 105, formatter: statusFormatter}, {title: "Статус", field: "status", width: 105, formatter: statusFormatter},
{title: "Приоритет", field: "priority", width: 85, formatter: priorityFormatter}, {title: "Приоритет", field: "priority", width: 105, formatter: priorityFormatter},
{title: "Заявка", field: "request_date", width: 85}, {title: "Заявка", field: "request_date_display", width: 105,
{title: "Карточка", field: "card_date", width: 85}, sorter: function(a, b, aRow, bRow) {
{title: "Планирование", field: "planned_at", width: 120}, const dateA = aRow.getData().request_date;
const dateB = bRow.getData().request_date;
if (!dateA && !dateB) return 0;
if (!dateA) return 1;
if (!dateB) return -1;
return new Date(dateA) - new Date(dateB);
}
},
{title: "Карточка", field: "card_date_display", width: 120,
sorter: function(a, b, aRow, bRow) {
const dateA = aRow.getData().card_date;
const dateB = bRow.getData().card_date;
if (!dateA && !dateB) return 0;
if (!dateA) return 1;
if (!dateB) return -1;
return new Date(dateA) - new Date(dateB);
}
},
{title: "Планирование", field: "planned_at_display", width: 150,
sorter: function(a, b, aRow, bRow) {
const dateA = aRow.getData().planned_at;
const dateB = bRow.getData().planned_at;
if (!dateA && !dateB) return 0;
if (!dateA) return 1;
if (!dateB) return -1;
return new Date(dateA) - new Date(dateB);
}
},
{title: "Down", field: "downlink", width: 65, hozAlign: "right", formatter: function(cell) { return numberFormatter(cell, 2); }}, {title: "Down", field: "downlink", width: 65, hozAlign: "right", formatter: function(cell) { return numberFormatter(cell, 2); }},
{title: "Up", field: "uplink", width: 65, hozAlign: "right", formatter: function(cell) { return numberFormatter(cell, 2); }}, {title: "Up", field: "uplink", width: 65, hozAlign: "right", formatter: function(cell) { return numberFormatter(cell, 2); }},
{title: "Пер.", field: "transfer", width: 50, hozAlign: "right", formatter: function(cell) { return numberFormatter(cell, 0); }}, {title: "Пер.", field: "transfer", width: 50, hozAlign: "right", formatter: function(cell) { return numberFormatter(cell, 0); }},
{title: "Коорд. ГСО", field: "coords_lat", width: 110, formatter: coordsFormatter}, {title: "Коорд. ГСО", field: "coords_lat", width: 130, formatter: coordsFormatter},
{title: "Район", field: "region", width: 80, formatter: function(cell) { {title: "Район", field: "region", width: 100, formatter: function(cell) {
const val = cell.getValue(); const val = cell.getValue();
return val ? val.substring(0, 12) + (val.length > 12 ? '...' : '') : '-'; return val ? val.substring(0, 12) + (val.length > 12 ? '...' : '') : '-';
}}, }},
{title: "ГСО", field: "gso_success", width: 50, hozAlign: "center", formatter: boolFormatter}, {title: "ГСО", field: "gso_success", width: 50, hozAlign: "center", formatter: boolFormatter},
{title: "Куб", field: "kubsat_success", width: 50, hozAlign: "center", formatter: boolFormatter}, {title: "Куб", field: "kubsat_success", width: 50, hozAlign: "center", formatter: boolFormatter},
{title: "Коорд. ист.", field: "coords_source_lat", width: 110, formatter: coordsFormatter}, {title: "Коорд. ист.", field: "coords_source_lat", width: 140, formatter: coordsFormatter},
{title: "Комментарий", field: "comment", width: 180, formatter: commentFormatter}, {title: "Комментарий", field: "comment", width: 180, formatter: commentFormatter},
{title: "Действия", field: "id", width: 105, formatter: actionsFormatter, headerSort: false}, {title: "Действия", field: "id", width: 105, formatter: actionsFormatter, headerSort: false},
], ],

View File

@@ -80,8 +80,17 @@ class KubsatView(LoginRequiredMixin, FormView):
# Сериализуем заявки в JSON для Tabulator # Сериализуем заявки в JSON для Tabulator
import json import json
from django.utils import timezone
requests_json_data = [] requests_json_data = []
for req in requests_list: for req in requests_list:
# Конвертируем даты в локальный часовой пояс для отображения
planned_at_local = None
planned_at_iso = None
if req.planned_at:
planned_at_local = timezone.localtime(req.planned_at)
planned_at_iso = planned_at_local.isoformat()
requests_json_data.append({ requests_json_data.append({
'id': req.id, 'id': req.id,
'source_id': req.source_id, 'source_id': req.source_id,
@@ -90,9 +99,18 @@ class KubsatView(LoginRequiredMixin, FormView):
'status_display': req.get_status_display(), 'status_display': req.get_status_display(),
'priority': req.priority, 'priority': req.priority,
'priority_display': req.get_priority_display(), 'priority_display': req.get_priority_display(),
'request_date': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-', # Даты в ISO формате для правильной сортировки
'card_date': req.card_date.strftime('%d.%m.%Y') if req.card_date else '-', 'request_date': req.request_date.isoformat() if req.request_date else None,
'planned_at': req.planned_at.strftime('%d.%m.%Y %H:%M') if req.planned_at else '-', 'card_date': req.card_date.isoformat() if req.card_date else None,
'planned_at': planned_at_iso,
# Отформатированные даты для отображения
'request_date_display': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-',
'card_date_display': req.card_date.strftime('%d.%m.%Y') if req.card_date else '-',
'planned_at_display': (
planned_at_local.strftime('%d.%m.%Y') if planned_at_local and planned_at_local.hour == 0 and planned_at_local.minute == 0
else planned_at_local.strftime('%d.%m.%Y %H:%M') if planned_at_local
else '-'
),
'downlink': float(req.downlink) if req.downlink else None, 'downlink': float(req.downlink) if req.downlink else None,
'uplink': float(req.uplink) if req.uplink else None, 'uplink': float(req.uplink) if req.uplink else None,
'transfer': float(req.transfer) if req.transfer else None, 'transfer': float(req.transfer) if req.transfer else None,

View File

@@ -8,6 +8,7 @@ from django.views import View
from django.views.generic import ListView, CreateView, UpdateView from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.db.models import Q from django.db.models import Q
from django.utils import timezone
from mainapp.models import SourceRequest, SourceRequestStatusHistory, Source, Satellite from mainapp.models import SourceRequest, SourceRequestStatusHistory, Source, Satellite
from mainapp.forms import SourceRequestForm from mainapp.forms import SourceRequestForm
@@ -200,7 +201,7 @@ class SourceRequestBulkDeleteView(LoginRequiredMixin, View):
return JsonResponse({ return JsonResponse({
'success': True, 'success': True,
'message': f'Удалено заявок: {deleted_count}', 'message': 'Заявки удалены',
'deleted_count': deleted_count 'deleted_count': deleted_count
}) })
except json.JSONDecodeError: except json.JSONDecodeError:
@@ -292,7 +293,14 @@ class SourceRequestExportView(LoginRequiredMixin, View):
ws.cell(row=row_num, column=2, value=req.card_date.strftime('%d.%m.%Y') if req.card_date else '') ws.cell(row=row_num, column=2, value=req.card_date.strftime('%d.%m.%Y') if req.card_date else '')
# Дата проведения # Дата проведения
ws.cell(row=row_num, column=3, value=req.planned_at.strftime('%d.%m.%y %H:%M') if req.planned_at else '') planned_at_local = timezone.localtime(req.planned_at) if req.planned_at else None
planned_at_str = ''
if planned_at_local:
if planned_at_local.hour == 0 and planned_at_local.minute == 0:
planned_at_str = planned_at_local.strftime('%d.%m.%y')
else:
planned_at_str = planned_at_local.strftime('%d.%m.%y %H:%M')
ws.cell(row=row_num, column=3, value=planned_at_str)
# Спутник # Спутник
satellite_str = '' satellite_str = ''
@@ -413,7 +421,7 @@ class SourceRequestAPIView(LoginRequiredMixin, View):
history.append({ history.append({
'old_status': h.get_old_status_display() if h.old_status else '-', 'old_status': h.get_old_status_display() if h.old_status else '-',
'new_status': h.get_new_status_display(), 'new_status': h.get_new_status_display(),
'changed_at': h.changed_at.strftime('%d.%m.%Y %H:%M') if h.changed_at else '-', 'changed_at': timezone.localtime(h.changed_at).strftime('%d.%m.%Y %H:%M') if h.changed_at else '-',
'changed_by': str(h.changed_by) if h.changed_by else '-', 'changed_by': str(h.changed_by) if h.changed_by else '-',
}) })
@@ -423,13 +431,18 @@ class SourceRequestAPIView(LoginRequiredMixin, View):
'status_display': req.get_status_display(), 'status_display': req.get_status_display(),
'priority': req.priority, 'priority': req.priority,
'priority_display': req.get_priority_display(), 'priority_display': req.get_priority_display(),
'planned_at': req.planned_at.strftime('%d.%m.%Y %H:%M') if req.planned_at else '-', 'planned_at': (
timezone.localtime(req.planned_at).strftime('%d.%m.%Y')
if req.planned_at and timezone.localtime(req.planned_at).hour == 0 and timezone.localtime(req.planned_at).minute == 0
else timezone.localtime(req.planned_at).strftime('%d.%m.%Y %H:%M') if req.planned_at
else '-'
),
'request_date': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-', 'request_date': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-',
'status_updated_at': req.status_updated_at.strftime('%d.%m.%Y %H:%M') if req.status_updated_at else '-', 'status_updated_at': timezone.localtime(req.status_updated_at).strftime('%d.%m.%Y %H:%M') if req.status_updated_at else '-',
'gso_success': req.gso_success, 'gso_success': req.gso_success,
'kubsat_success': req.kubsat_success, 'kubsat_success': req.kubsat_success,
'comment': req.comment or '-', 'comment': req.comment or '-',
'created_at': req.created_at.strftime('%d.%m.%Y %H:%M') if req.created_at else '-', 'created_at': timezone.localtime(req.created_at).strftime('%d.%m.%Y %H:%M') if req.created_at else '-',
'created_by': str(req.created_by) if req.created_by else '-', 'created_by': str(req.created_by) if req.created_by else '-',
'history': history, 'history': history,
}) })
@@ -464,7 +477,7 @@ class SourceRequestDetailAPIView(LoginRequiredMixin, View):
history.append({ history.append({
'old_status': h.get_old_status_display() if h.old_status else '-', 'old_status': h.get_old_status_display() if h.old_status else '-',
'new_status': h.get_new_status_display(), 'new_status': h.get_new_status_display(),
'changed_at': h.changed_at.strftime('%d.%m.%Y %H:%M') if h.changed_at else '-', 'changed_at': timezone.localtime(h.changed_at).strftime('%d.%m.%Y %H:%M') if h.changed_at else '-',
'changed_by': str(h.changed_by) if h.changed_by else '-', 'changed_by': str(h.changed_by) if h.changed_by else '-',
}) })
@@ -499,13 +512,18 @@ class SourceRequestDetailAPIView(LoginRequiredMixin, View):
'status_display': req.get_status_display(), 'status_display': req.get_status_display(),
'priority': req.priority, 'priority': req.priority,
'priority_display': req.get_priority_display(), 'priority_display': req.get_priority_display(),
'planned_at': req.planned_at.strftime('%Y-%m-%dT%H:%M') if req.planned_at else '', 'planned_at': timezone.localtime(req.planned_at).strftime('%Y-%m-%dT%H:%M') if req.planned_at else '',
'planned_at_display': req.planned_at.strftime('%d.%m.%Y %H:%M') if req.planned_at else '-', 'planned_at_display': (
timezone.localtime(req.planned_at).strftime('%d.%m.%Y')
if req.planned_at and timezone.localtime(req.planned_at).hour == 0 and timezone.localtime(req.planned_at).minute == 0
else timezone.localtime(req.planned_at).strftime('%d.%m.%Y %H:%M') if req.planned_at
else '-'
),
'request_date': req.request_date.isoformat() if req.request_date else None, 'request_date': req.request_date.isoformat() if req.request_date else None,
'request_date_display': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-', 'request_date_display': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-',
'card_date': req.card_date.isoformat() if req.card_date else None, 'card_date': req.card_date.isoformat() if req.card_date else None,
'card_date_display': req.card_date.strftime('%d.%m.%Y') if req.card_date else '-', 'card_date_display': req.card_date.strftime('%d.%m.%Y') if req.card_date else '-',
'status_updated_at': req.status_updated_at.strftime('%d.%m.%Y %H:%M') if req.status_updated_at else '-', 'status_updated_at': timezone.localtime(req.status_updated_at).strftime('%d.%m.%Y %H:%M') if req.status_updated_at else '-',
'downlink': req.downlink, 'downlink': req.downlink,
'uplink': req.uplink, 'uplink': req.uplink,
'transfer': req.transfer, 'transfer': req.transfer,
@@ -513,7 +531,7 @@ class SourceRequestDetailAPIView(LoginRequiredMixin, View):
'gso_success': req.gso_success, 'gso_success': req.gso_success,
'kubsat_success': req.kubsat_success, 'kubsat_success': req.kubsat_success,
'comment': req.comment or '', 'comment': req.comment or '',
'created_at': req.created_at.strftime('%d.%m.%Y %H:%M') if req.created_at else '-', 'created_at': timezone.localtime(req.created_at).strftime('%d.%m.%Y %H:%M') if req.created_at else '-',
'created_by': str(req.created_by) if req.created_by else '-', 'created_by': str(req.created_by) if req.created_by else '-',
'history': history, 'history': history,
# Координаты ГСО # Координаты ГСО

1
dbapp/static/luxon/luxon.min.js vendored Normal file

File diff suppressed because one or more lines are too long