2023-08-21 03:28:58 +00:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Записи< / title >
< link rel = "stylesheet" href = "../styles/main.css" / >
2023-08-22 15:29:23 +00:00
< link rel = "stylesheet" href = "https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" / >
< script src = "https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" > < / script >
2024-01-08 22:39:00 +00:00
< style >
.stream-cameras {
width: 100%;
max-height: 450px;
display: none;
}
< / style >
2023-08-21 03:28:58 +00:00
< / head >
< body >
2024-01-08 22:39:00 +00:00
< div id = "video-popup" class = "video-popup" >
< div id = "video-popup-content" class = "video-popup-content" >
< span class = "close-popup" id = "close-popup" > × < / span >
< div id = "popup-video-container" class = "popup-video-container" >
< / div >
< / div >
< / div >
2023-08-21 03:28:58 +00:00
< header >
2023-09-18 01:58:49 +00:00
< img src = "../img/argus.png" >
2023-08-21 03:28:58 +00:00
< h1 > А р г у с < / h1 >
< h2 > < span > /< / span > {{Organisation}}< / h2 >
< / header >
< section class = "account-info" >
< div id = "account-main" >
< img id = "person" src = "../img/person.svg" >
< span > {{User}}< / span >
< img id = "down" src = "../img/down.svg" >
< img id = "up" src = "../img/up.svg" >
< / div >
2023-09-11 09:57:10 +00:00
< a href = "/logout" > < div id = "account-additional" class = "additional" > Выйти< / div > < / a >
2023-08-21 03:28:58 +00:00
< / section >
< section class = "navigation" >
< a href = "/" >
< div > < img src = "../img/chart.svg" > Главная< / div >
< / a >
< a href = "/devices" >
< div > < img src = "../img/cloud.svg" > Устройства< / div >
< / a >
< a href = "/reports" >
< div > < img src = "../img/bubble.svg" > Отчёты< / div >
< / a >
< a href = "/live" >
< div > < img src = "../img/waves.svg" > Трансляция< / div >
< / a >
< a href = "/videos" >
< div class = "selected" > < img src = "../img/play.svg" > Записи< / div >
< / a >
2023-09-28 21:37:39 +00:00
< a href = "https://forms.yandex.ru/cloud/6515ecda3e9d08f17262c332/" target = "_blank" >
< div > < img src = "../img/bug.svg" > Собщить о б ошибке< / div >
< / a >
2023-09-11 09:57:10 +00:00
{{#if isAdmin}}
2023-09-11 05:59:00 +00:00
< a class = "admin-panel" href = "/admin" >
2023-09-11 09:57:10 +00:00
< div > < img src = "../img/keyboard.svg" > Админка< / div >
2023-09-11 05:59:00 +00:00
< / a >
2023-09-11 09:57:10 +00:00
{{/if}}
2023-08-28 04:40:58 +00:00
< a class = "settings" href = "/settings" >
2023-08-21 03:28:58 +00:00
< div > < img src = "../img/gear.svg" > Настройки< / div >
< / a >
< / section >
< section class = "main" >
2023-09-17 12:22:14 +00:00
< section style = "display: none;" class = "dberror" id = "dataLoading" >
< div class = "loader-container" >
< div class = "loader" >
< div class = "square" id = "sq11" > < / div >
< div class = "square" id = "sq12" > < / div >
< div class = "square" id = "sq13" > < / div >
< div class = "square" id = "sq14" > < / div >
< div class = "square" id = "sq15" > < / div >
< div class = "square" id = "sq16" > < / div >
< div class = "square" id = "sq17" > < / div >
< div class = "square" id = "sq18" > < / div >
< div class = "square" id = "sq19" > < / div >
< / div >
< / div >
< / section >
2023-08-21 03:28:58 +00:00
{{#if ifDBError}}
< section class = "dberror" >
< div class = "erorr-container" >
< img src = "../img/warning.svg" > < br >
< h1 > Ошибка < / h1 > < br >
< span > Н е удалось получить данные из БД< / span >
< button type = "button" onclick = "location.reload();" > Повторить попытку< / button >
< / div >
< / section >
{{/if}}
< nav >
< a class = "selected" href = "/videos" > Воспроизведение< / a >
2023-08-28 11:25:45 +00:00
< a href = "/videos/export" > Экспорт< / a >
2023-08-21 03:28:58 +00:00
< / nav >
< section class = "bg" >
< section class = "content" >
2023-09-04 09:11:22 +00:00
< section style = "min-height: 800px;" class = "for-table" >
2023-08-21 03:28:58 +00:00
< section class = "organisation" >
< h1 > Организация< / h1 >
< ul class = "area" >
2023-09-04 09:11:22 +00:00
{{#each Groups}}
2023-10-06 00:57:23 +00:00
< li class = "area-name" > < img src = "../img/ul.svg" > < input type = "checkbox" id = "{{name}}" class = "checkbox-input" hidden checked > < label for = "{{name}}" class = "checkbox-label checkbox-name" > < span class = "text" > {{name}}< / span > < / label >
2023-08-21 03:28:58 +00:00
< ul class = "area-devices" id = "devices-1" >
2023-09-04 09:11:22 +00:00
{{#each devices}}
< li class = "device" >
< img >
2023-09-17 12:22:14 +00:00
< input type = "number" id = "channels-{{this.serial}}" value = "{{this.channels}}" hidden >
2023-09-04 09:11:22 +00:00
< input type = "radio" name = "camera-serial" id = "radio-{{this.serial}}" class = "radio-input" value = "{{this.serial}}" hidden >
2024-01-08 22:39:00 +00:00
< input type = "text" id = "ourreg-{{this.serial}}" value = "{{this.ourreg}}" hidden >
2023-09-14 02:40:03 +00:00
< label for = "radio-{{this.serial}}" class = "radio-label active-{{this.status}}" >
2023-09-19 13:31:40 +00:00
{{#if this.number}}
{{this.number}}
{{else}}
{{this.serial}}
{{/if}}
2023-09-04 09:11:22 +00:00
< / label >
< / li >
{{/each}}
2023-08-21 03:28:58 +00:00
< / ul >
< / li >
2023-09-04 09:11:22 +00:00
{{/each}}
< / ul >
2023-08-21 03:28:58 +00:00
< / section >
< section class = "table" style = "position: relative;" >
< div class = "map" >
< div id = "map" > < / div >
< / div >
2023-09-17 12:22:14 +00:00
< div style = "background: white;" class = "cameras" >
< section style = "border: 0;" class = "whole-width" >
< h1 > Запустить запись с камеры< / h1 >
2024-01-08 22:39:00 +00:00
< h3 id = "cameras-title" > Выберите камеру, время и нажмите кнопку "Запустить запись"< / h3 >
2023-09-17 12:22:14 +00:00
< form id = "edit-group-form" >
< div class = "parameters-input" >
< label for = "group-id" > Камера< / label >
< select name = "group-id" id = "group-id" >
< option value = "" > Выберите номер камеры< / option >
< option value = "1" > Камера 1< / option >
< option value = "2" > Камера 2< / option >
< option value = "3" > Камера 3< / option >
< option value = "4" > Камера 4< / option >
< option value = "5" > Камера 5< / option >
< option value = "6" > Камера 6< / option >
< option value = "7" > Камера 7< / option >
< option value = "8" > Камера 8< / option >
< option value = "9" > Камера 9< / option >
< option value = "10" > Камера 10< / option >
< option value = "11" > Камера 11< / option >
< option value = "12" > Камера 12< / option >
< option value = "13" > Камера 13< / option >
< / select >
2023-08-21 03:28:58 +00:00
< / div >
2023-09-17 12:22:14 +00:00
< / form >
< div style = "margin-left: 44px; margin-right: 72px; width: calc(100% - 44px - 72px);" class = "horizontal-line" > < / div >
< button style = "margin-top: 15px;" id = "group-edit" class = "button-purple" type = "button" onclick = "playVideo();" > Запустить запись< / button >
2024-01-08 22:39:00 +00:00
< h3 id = "warning" > Могут возникнуть проблемы с блокировкой всплывающих окон в браузере, при возникновении проблем проверьте что открытие новых окон из этого сайта у вас работает (обычно иконка отображается в правом верхнем углу).< / h3 >
< br >
<!-- <video id="playback - camera"></video> -->
< div id = "playback-cameras" class = "stream-cameras" >
< div class = "stream-video-container" >
< video id = "camera-1" > < / video >
< video id = "camera-2" > < / video >
< video id = "camera-3" > < / video >
< video id = "camera-4" > < / video >
< video style = "display: none;" id = "camera-5" > < / video >
< / div >
< button onclick = "switchCameras(-1)" > Назад< / button >
< button onclick = "switchCameras(1)" > Вперед< / button >
< / div >
2023-09-17 12:22:14 +00:00
< / section >
2023-08-21 03:28:58 +00:00
< / div >
2023-09-17 12:22:14 +00:00
2023-08-21 03:28:58 +00:00
< div class = "calendar" >
< div class = "calendar-header" >
< button id = "prevMonth" > < / button >
< h2 id = "monthYear" > < / h2 >
< button id = "nextMonth" > < / button >
< / div >
< div class = "daysOfWeek" >
< div > Пн< / div >
< div > Вт< / div >
< div > С р < / div >
< div > Чт< / div >
< div > Пт< / div >
< div > С б < / div >
< div > В с < / div >
< / div >
< div class = "dates" id = "dates" >
< / div >
< / div >
< input type = "hidden" id = "selectedDate" name = "selectedDate" hidden >
< div class = "speedometr" >
2023-08-28 11:25:45 +00:00
< div style = "display: none;" id = "speed-bg" class = "speed-bg" >
< h1 > Данных для выбранного периода нет.< / h1 >
< / div >
2023-08-21 03:28:58 +00:00
< h1 > Скорость< / h1 >
< span > км/ч< / span >
< span style = "float: right; font-size: 18px;" > 1 ч< / span >
< div >
< canvas id = "speed" > < / canvas >
< / div >
< / div >
< div class = "video-time" >
2024-01-08 22:39:00 +00:00
<!-- <span id="from - time - label" style="margin - left: 15px; display: none;">с </span> -->
2023-08-21 03:28:58 +00:00
< input name = "videoTime" type = "time" id = "video-time" step = "1" >
2024-01-08 22:39:00 +00:00
<!-- <span id="end - time - label" style="display: none;">до</span> -->
<!-- <input name="videoEndTime" type="time" id="video - end - time" step="1" style="display: none;"> -->
2023-08-21 03:28:58 +00:00
< / div >
< / section >
< / section >
< / section >
< / section >
< / section >
< style >
.table {
2023-09-18 01:58:49 +00:00
background-color:#f7f7fa !important;
2023-08-21 03:28:58 +00:00
}
.speedometr {
position: absolute;
right: 0;
bottom: 62px;
width: calc(75% - 300px - 10px - 32px);
height: 220px;
border-radius: 15px;
background-color: white;
padding-right: 32px;
}
.speedometr div {
2023-09-17 12:22:14 +00:00
height: 190px;
2023-08-21 03:28:58 +00:00
}
< / style >
< script src = "../scripts/jquery.min.js" > < / script >
< script src = "https://cdn.jsdelivr.net/npm/chart.js" > < / script >
2024-01-08 22:39:00 +00:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.5.0/flv.min.js" > < / script >
2023-08-21 03:28:58 +00:00
2023-10-06 00:57:23 +00:00
< script >
document.addEventListener('DOMContentLoaded', function () {
var containers = document.querySelectorAll('.checkbox-name');
containers.forEach(function (container) {
var text = container.querySelector('.text');
if (text.clientWidth > container.clientWidth) {
text.classList.add('animated');
}
});
});
2023-10-15 23:57:17 +00:00
document.addEventListener('DOMContentLoaded', function () {
var radioLabels = document.querySelectorAll('.radio-label');
radioLabels.forEach(function (label) {
var labelText = label.textContent.trim();
if (labelText.length > 10) {
label.textContent = '';
label.appendChild(document.createTextNode(labelText.slice(0, 9) + '...'));
}
});
});
2023-10-06 00:57:23 +00:00
< / script >
2023-09-17 12:22:14 +00:00
< script >
function updateCameraOptions() {
var selectedSerial = document.querySelector('input[name="camera-serial"]:checked').value;
var channelsInput = document.querySelector('#channels-' + selectedSerial);
var numChannels = parseInt(channelsInput.value, 10);
var select = document.querySelector('#group-id');
select.innerHTML = '';
var defaultOption = document.createElement('option');
defaultOption.value = '';
defaultOption.textContent = 'Выберите номер камеры';
select.appendChild(defaultOption);
for (var i = 1; i < = numChannels; i++) {
var option = document.createElement('option');
option.value = i;
option.textContent = 'Камера ' + i;
select.appendChild(option);
}
}
< / script >
2023-09-04 09:11:22 +00:00
< script >
document.addEventListener('DOMContentLoaded', function () {
const areaNames = document.querySelectorAll('.area-name');
areaNames.forEach(function (areaName) {
const areaCheckbox = areaName.querySelector('.checkbox-input');
const deviceCheckboxes = areaName.querySelectorAll('.device .checkbox-input');
const deviceList = areaName.querySelector('.area-devices');
// Функция для скрытия/показа дочерних элементов
function toggleChildDevices(show) {
if (show) {
deviceList.style.display = 'block';
} else {
deviceList.style.display = 'none';
}
}
// Инициализация состояния чекбоксов и скрытия/показа дочерних элементов
toggleChildDevices(areaCheckbox.checked);
deviceCheckboxes.forEach(function (deviceCheckbox) {
deviceCheckbox.checked = areaCheckbox.checked;
});
areaCheckbox.addEventListener('change', function () {
const isChecked = areaCheckbox.checked;
deviceCheckboxes.forEach(function (deviceCheckbox) {
deviceCheckbox.checked = isChecked;
});
toggleChildDevices(isChecked);
});
deviceCheckboxes.forEach(function (deviceCheckbox) {
deviceCheckbox.addEventListener('change', function () {
const allUnchecked = Array.from(deviceCheckboxes).every(function (checkbox) {
return !checkbox.checked;
});
if (allUnchecked) {
areaCheckbox.checked = false;
toggleChildDevices(false);
} else {
areaCheckbox.checked = true;
toggleChildDevices(true);
}
});
});
});
});
< / script >
2023-08-21 03:28:58 +00:00
< script >
function combineDateTime(dateString, timeString) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
// Разбиение времени на часы, минуты и секунды
const timeParts = timeString.split(":");
const hours = timeParts[0].padStart(2, "0");
const minutes = timeParts[1].padStart(2, "0");
const seconds = timeParts[2].padStart(2, "0");
// Собираем дату и время в нужном формате
const combinedDateTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
return combinedDateTime;
}
2023-08-28 11:25:45 +00:00
let HasData;
var selectedChannel = 1;
async function sendPostRequest() {
2024-01-08 22:39:00 +00:00
stopAllCameras();
let serial = $("input[name=camera-serial]:checked").val()
if ($(`#ourreg-${serial}`).val() == "true") {
$("#warning").hide();
$("#playback-cameras").show();
$("#edit-group-form").hide();
$("#cameras-title").hide();
// $("#from-time-label").show();
// $("#end-time-label").show();
// $("#video-end-time").show();
} else {
$("#warning").show();
$("#playback-cameras").hide();
$("#edit-group-form").show();
$("#cameras-title").show();
// $("#from-time-label").hide();
// $("#end-time-label").hide();
// $("#video-end-time").hide();
}
2023-09-17 12:22:14 +00:00
updateCameraOptions();
document.getElementById("dataLoading").style.display = 'flex';
2023-08-21 03:28:58 +00:00
// Получение данных из полей ввода
const selectedDate = document.getElementById("selectedDate").value;
const videoTime = document.getElementById("video-time").value;
const selectedSerial = document.querySelector('input[name="camera-serial"]:checked').value;
2023-08-28 11:25:45 +00:00
2023-08-21 03:28:58 +00:00
// Объединяем дату и время и преобразуем в нужный формат
const combinedDateTime = combineDateTime(selectedDate, videoTime);
2023-08-28 11:25:45 +00:00
const response = await fetch(`/getData?serial=${selectedSerial}&selectedDate=${formatDate(selectedDate)}&selectedTime=${formatTime(videoTime)}&selectedChannel=${selectedChannel}`);
const data = await response.json();
2023-10-04 21:17:14 +00:00
console.log(data);
2023-08-28 11:25:45 +00:00
HasData = data.success;
if (data.success) {
console.log(`Данные доступны. DATAID: ${data.dataId}`)
2023-10-04 21:23:12 +00:00
document.getElementById("speed-bg").style.display = "none";
2023-08-28 11:25:45 +00:00
const requestData = {
serial: selectedSerial,
datetime: combinedDateTime,
};
fetch("/getspeedarchive", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestData),
})
.then((response) => response.json())
.then((data) => {
2023-09-17 12:22:14 +00:00
document.getElementById("dataLoading").style.display = 'none';
2023-09-04 09:11:22 +00:00
2023-08-28 11:25:45 +00:00
const existingChart = Chart.getChart("speed");
if (existingChart) {
existingChart.destroy();
}
const numberOfLabels = data.speeds.length;
2023-09-17 12:22:14 +00:00
// const labels = Array.from({ length: numberOfLabels }, () => "");
2023-08-28 11:25:45 +00:00
// Обновление данных графика
const chart = new Chart("speed", {
type: "line",
data: {
2023-09-17 12:22:14 +00:00
labels: data.names,
2023-08-28 11:25:45 +00:00
datasets: [
{
label: "Скорость",
borderColor: "#8086F9",
fill: false,
data: data.speeds,
pointStyle: false,
pointRadius: 25,
pointHoverRadius: 25,
tension: 0.1,
},
],
},
options: {
plugins: {
legend: {
display: false,
},
},
labelStep: "3",
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
stacked: true,
grid: {
display: true,
color: "#D9D9D9",
},
ticks: {
stepSize: 10,
},
},
x: {
2023-09-17 12:22:14 +00:00
ticks: {
autoSkip: false,
callback: function(value, index, values) {
const data = this.chart.data.labels;
if (index === 0 || index === values.length - 1) {
return data[index];
} else {
return '';
}
},
position: 'bottom',
maxRotation: 0,
},
2023-08-28 11:25:45 +00:00
grid: {
display: false,
},
},
},
},
});
const geoData = data.geo;
// Очищаем все слои на карте
map.eachLayer(layer => {
if (layer !== map) {
map.removeLayer(layer);
}
});
// Добавляем слой с плитками OpenStreetMap
2023-10-03 13:16:38 +00:00
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
2023-08-28 11:25:45 +00:00
// Создаем слой для маршрута
const routeLayer = L.layerGroup().addTo(map);
// Создаем слой для маркеров
const markerLayer = L.layerGroup().addTo(map);
// Преобразуем координаты точек маршрута
const routePoints = geoData.map(point => [point.latitude, point.longitude]);
// Создаем линию маршрута
const route = L.polyline(routePoints, { color: 'red',weight: 5 }).addTo(routeLayer);
2023-10-06 00:57:23 +00:00
// Находим границы координат для центрирования карты
const bounds = L.latLngBounds(routePoints);
// Центрируем карту по первой координате
map.fitBounds(bounds, { padding: [50, 50] });
2023-08-28 11:25:45 +00:00
})
.catch((error) => {
2023-09-17 12:22:14 +00:00
document.getElementById("dataLoading").style.display = 'none';
var h1Element = document.querySelector('.speedometr h1');
h1Element.textContent = 'Ошибка отправки запроса.';
2023-08-28 11:25:45 +00:00
console.error("Ошибка при отправке запроса:", error);
});
} else {
2023-09-17 12:22:14 +00:00
const existingChart = Chart.getChart("speed");
if (existingChart) {
existingChart.destroy();
}
const chart = new Chart("speed", {
type: "line",
data: {
labels: "",
datasets: [
{
label: "Скорость",
borderColor: "#8086F9",
fill: false,
data: "",
pointStyle: false,
pointRadius: 25,
pointHoverRadius: 25,
tension: 0.1,
},
],
},
options: {
plugins: {
legend: {
display: false,
},
},
labelStep: "3",
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
stacked: true,
grid: {
display: true,
color: "#D9D9D9",
},
ticks: {
stepSize: 10,
},
},
x: {
grid: {
display: false,
},
},
},
},
});
2023-10-04 21:17:14 +00:00
document.getElementById("dataLoading").style.display = 'none';
2023-08-28 11:25:45 +00:00
const speedBG = document.getElementById("speed-bg");
speedBG.style.display = 'flex';
}
2023-08-21 03:28:58 +00:00
2023-08-28 11:25:45 +00:00
2023-08-21 03:28:58 +00:00
}
const radioInputs = document.querySelectorAll(".radio-input");
radioInputs.forEach((input) => {
input.addEventListener("change", sendPostRequest);
});
const selectedDateInput = document.getElementById("selectedDate");
selectedDateInput.addEventListener("change", sendPostRequest);
const videoTimeInput = document.getElementById("video-time");
2023-09-17 12:22:14 +00:00
videoTimeInput.addEventListener("blur", sendPostRequest);
2023-08-21 03:28:58 +00:00
< / script >
2024-01-08 22:39:00 +00:00
< script >
var now = new Date();
now.setHours(now.getHours() - 1);
var formattedTime = now.toISOString().substr(11, 8);
document.getElementById("video-time").value = formattedTime;
// const startTimeInput = document.getElementById('video-time');
// const endTimeInput = document.getElementById('video-end-time');
// const startTime = new Date(`1970-01-01T${startTimeInput.value}Z`);
// startTime.setHours(startTime.getHours() - 3);
// startTime.setSeconds(startTime.getSeconds() + 60);
// const hours = startTime.getHours().toString().padStart(2, '0');
// const minutes = startTime.getMinutes().toString().padStart(2, '0');
// const seconds = startTime.getSeconds().toString().padStart(2, '0');
// const endTimeString = `${hours}:${minutes}:${seconds}`;
// endTimeInput.value = endTimeString;
< / script >
2023-08-21 03:28:58 +00:00
< script >
document.addEventListener("DOMContentLoaded", function () {
const prevMonthBtn = document.getElementById("prevMonth");
const nextMonthBtn = document.getElementById("nextMonth");
const monthYear = document.getElementById("monthYear");
const datesContainer = document.getElementById("dates");
const dateForm = document.getElementById("dateForm");
const selectedDateInput = document.getElementById("selectedDate");
let currentDate = new Date();
let selectedDate = currentDate;
selectedDateInput.value = selectedDate.toISOString();
function renderCalendar() {
// Очистить предыдущий календарь
datesContainer.innerHTML = "";
// Установить заголовок с месяцем и годом
const options = { year: "numeric", month: "long" };
const formattedDate = currentDate.toLocaleDateString("ru-RU", options);
const formattedMonthYear = formattedDate.charAt(0).toUpperCase() + formattedDate.slice(1);
monthYear.textContent = formattedMonthYear.replace('г .', '');
// Найти первый день текущего месяца
const firstDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
// Определить день недели, с которого начнется месяц
const startingDay = firstDayOfMonth.getDay() - 1;
// Определить количество дней в текущем месяце
const daysInMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0).getDate();
// Создать дни месяца
for (let i = 0; i < startingDay ; i + + ) {
const emptyDay = document.createElement("div");
emptyDay.classList.add("empty-day");
datesContainer.appendChild(emptyDay);
}
for (let day = 1; day < = daysInMonth; day++) {
const dateCell = document.createElement("div");
dateCell.textContent = day;
dateCell.classList.add("date");
if (selectedDate.getDate() === day & & selectedDate.getMonth() === currentDate.getMonth() & & selectedDate.getFullYear() === currentDate.getFullYear()) {
dateCell.classList.add("selected");
}
dateCell.addEventListener("click", () => {
selectedDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), day);
renderCalendar();
selectedDateInput.value = selectedDate.toISOString();
2023-08-28 11:25:45 +00:00
sendPostRequest();
2023-08-21 03:28:58 +00:00
});
datesContainer.appendChild(dateCell);
}
2023-08-28 11:25:45 +00:00
2023-08-21 03:28:58 +00:00
}
// Перейти на предыдущий месяц
prevMonthBtn.addEventListener("click", () => {
currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, 1);
renderCalendar();
});
// Перейти на следующий месяц
nextMonthBtn.addEventListener("click", () => {
currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1);
renderCalendar();
});
// Инициализировать календарь
renderCalendar();
});
< / script >
2023-08-28 04:40:58 +00:00
< script >
function formatDate(selectedDate) {
const date = new Date(selectedDate);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return `${year}${month}${day}`;
}
2023-08-21 03:28:58 +00:00
2023-08-28 04:40:58 +00:00
function formatTime(videoTime) {
const parts = videoTime.split(':');
const hours = parts[0].toString().padStart(2, '0');
const minutes = parts[1].toString().padStart(2, '0');
const seconds = parts[2].toString().padStart(2, '0');
return `${hours}${minutes}${seconds}`;
}
function addOneHourToTime(videoTime) {
2023-08-21 03:28:58 +00:00
const parts = videoTime.split(':');
2023-08-28 04:40:58 +00:00
let hours = parseInt(parts[0], 10);
hours += 1;
2023-08-21 03:28:58 +00:00
const minutes = parts[1].toString().padStart(2, '0');
const seconds = parts[2].toString().padStart(2, '0');
2023-08-28 04:40:58 +00:00
return formatTime(`${hours}:${minutes}:${seconds}`);
2023-08-21 03:28:58 +00:00
}
2024-01-08 22:39:00 +00:00
2023-09-17 12:22:14 +00:00
function playVideo() {
const channel = document.getElementById("group-id").value;
2023-08-28 04:40:58 +00:00
const selectedDevice = document.querySelector('input[name="camera-serial"]:checked');
if (!selectedDevice) {
alert('Пожалуйста, выберите устройство из списка.');
return;
}
2024-01-08 22:39:00 +00:00
const startTimeInput = document.getElementById('video-time');
const selectedDateInput = document.getElementById('selectedDate');
const startTime = formatTime(startTimeInput.value);
const selectedDate = formatDate(selectedDateInput.value);
const endTime = addOneHourToTime(startTimeInput.value);
const serial = selectedDevice.value;
selectedChannel = channel;
if ($(`#ourreg-${serial}`).val() == "true") {
playNextCamerasInGroup();
} else {
if (channel === "") {
2023-09-17 12:22:14 +00:00
alert('Пожалуйста, выберите камеру из списка.');
return;
}
2023-08-28 11:25:45 +00:00
if (!HasData) {
alert('Пожалуйста, выберите другой временной период.');
return;
}
2024-01-08 22:39:00 +00:00
const url = `http://localhost:8081/playback?url=https%3A%2F%2F{{VIRTUAL_HOST}}%2Fhttp%2Fplayback.flv%3Fserial%3D${serial}%26channel%3D${channel}%26quality%3D1%26queryTime%3D${selectedDate}%26startTime%3D${startTime}%26endTime%3D${endTime}`;
window.open(url, '_blank');
}
}
< / script >
2023-08-28 11:25:45 +00:00
2024-01-08 22:39:00 +00:00
< script >
let flvPlayers = [];
let currentCameraGroup = 1;
const camerasPerGroup = 5;
var totalCameras = 12 - 1;
const isSecure = window.location.protocol === "https:";
const baseURL = "https://{{VIRTUAL_HOST}}/http/playback.flv";
function stopAllCameras() {
flvPlayers.forEach(player => {
player.pause();
player.unload();
player.detachMediaElement();
player.destroy();
});
flvPlayers = [];
}
async function playNextCamerasInGroup() {
const channel = document.getElementById("group-id").value;
const selectedDevice = document.querySelector('input[name="camera-serial"]:checked');
2023-08-21 03:28:58 +00:00
2023-08-28 04:40:58 +00:00
const startTimeInput = document.getElementById('video-time');
2024-01-08 22:39:00 +00:00
// const endTimeInput = document.getElementById('video-end-time');
2023-08-28 04:40:58 +00:00
const selectedDateInput = document.getElementById('selectedDate');
const startTime = formatTime(startTimeInput.value);
2024-01-08 22:39:00 +00:00
// const endTime = formatTime(endTimeInput.value);
2023-08-28 04:40:58 +00:00
const selectedDate = formatDate(selectedDateInput.value);
2023-08-21 03:28:58 +00:00
2024-01-08 22:39:00 +00:00
// const endTime = addOneHourToTime(startTimeInput.value);
2023-08-21 03:28:58 +00:00
2023-08-28 04:40:58 +00:00
const serial = selectedDevice.value;
2023-08-21 03:28:58 +00:00
2023-08-28 11:25:45 +00:00
selectedChannel = channel;
2024-01-08 22:39:00 +00:00
let startCamera;
let endCamera;
if ($(`#ourreg-${serial}`).val() == "true") {
startCamera = currentCameraGroup === 1 ? 1 : (currentCameraGroup - 1) * camerasPerGroup;
endCamera = startCamera + camerasPerGroup - 1;
} else {
startCamera = currentCameraGroup === 1 ? 2 : (currentCameraGroup - 1) * camerasPerGroup + 1;
endCamera = startCamera + camerasPerGroup - 1;
}
if (startCamera > totalCameras) {
return;
}
stopAllCameras();
let videoElementIndex = 1;
for (let i = startCamera; i < = endCamera & & i < = totalCameras; i++) {
const videoElement = document.getElementById(`camera-${videoElementIndex}`);
let flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
cors: true,
url: `${baseURL}?serial=${serial}& channel=${i}& quality=1& queryTime=${selectedDate}& startTime=${startTime}`,
}, {
enableWorker: true,
enableStashBuffer: false,
autoCleanupSourceBuffer: true,
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
flvPlayers.push(flvPlayer);
let hasStarted = false;
const checkStarted = () => {
if (!hasStarted & & videoElement.readyState >= 2) {
hasStarted = true;
console.log(`Трансляция началась для камеры ${i}`);
2023-08-28 04:40:58 +00:00
}
2024-01-08 22:39:00 +00:00
};
const checkInterval = setInterval(checkStarted, 1000);
setTimeout(() => {
clearInterval(checkInterval);
if (!hasStarted) {
console.log(`Трансляция для камеры ${i} не началась, запрашиваем повторно...`);
flvPlayer.unload();
flvPlayer.load();
flvPlayer.play();
// if (i > 0) {
// i--;
// }
}
}, 3000);
videoElementIndex++;
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
function switchCameras(direction) {
if ((currentCameraGroup === 1 & & direction === -1) || (currentCameraGroup === Math.ceil(totalCameras / camerasPerGroup) & & direction === 1)) {
return;
}
currentCameraGroup += direction;
if (currentCameraGroup < 1 ) {
currentCameraGroup = Math.ceil(totalCameras / camerasPerGroup);
} else if (currentCameraGroup > Math.ceil(totalCameras / camerasPerGroup)) {
currentCameraGroup = 1;
}
playNextCamerasInGroup();
}
2023-08-28 04:40:58 +00:00
< / script >
2023-08-21 03:28:58 +00:00
2023-08-21 03:52:58 +00:00
2023-08-28 04:40:58 +00:00
2023-08-21 03:28:58 +00:00
< script >
window.addEventListener('DOMContentLoaded', function() {
var mapContainer = document.querySelector('.map');
var mapArea = document.getElementById('map');
mapArea.style.height = (mapContainer.clientHeight) + 'px';
mapArea.style.width = (mapContainer.clientWidth) + 'px';
});
window.addEventListener("resize", function (event) {
var mapContainer = document.querySelector('.map');
var mapArea = document.getElementById('map');
mapArea.style.height = (mapContainer.clientHeight) + 'px';
mapArea.style.width = (mapContainer.clientWidth) + 'px';
});
2023-08-22 15:29:23 +00:00
var startPoint = [0, 0];
var endPoint = [0, 0];
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
let map;
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
// Создаем карту Leaflet
map = L.map('map').setView([59.855198, 30.282995], 10);
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
// Добавляем базовый слой OpenStreetMap
2023-10-03 13:16:38 +00:00
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
// Создаем маркеры
var startMarker = L.marker(startPoint, {
icon: L.divIcon({
className: 'custom-icon',
html: '< div style = "background-color: red; width: 14px; height: 14px; border: 2px solid white; border-radius: 50%;" > < / div > '
})
}).addTo(map);
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
var endMarker = L.marker(endPoint, {
icon: L.divIcon({
className: 'custom-icon',
html: '< div style = "background-color: red; width: 14px; height: 14px; border: 2px solid white; border-radius: 50%;" > < / div > '
})
}).addTo(map);
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
// Создаем линию маршрута
var route = L.polyline([startPoint, endPoint], { color: 'red', weight: 6 }).addTo(map);
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
// Скрыть кнопки приближения/отдаления
map.zoomControl.remove();
2023-08-21 03:28:58 +00:00
2023-08-22 15:29:23 +00:00
// Скрыть информационную панель
map.attributionControl.remove();
2023-08-21 03:28:58 +00:00
< / script >
< script >
// Скрытие/Показ дополнительных меню аккаунта
const accountMain = document.getElementById('account-main');
const accountAdditional = document.getElementById('account-additional');
const accountUp = document.getElementById('up');
const accountDown = document.getElementById('down');
accountAdditional.style.display = 'none';
accountUp.style.display = 'none';
accountMain.addEventListener('click', () => {
if (accountAdditional.style.display === 'none') {
accountAdditional.style.display = 'flex';
accountUp.style.display = 'unset';
accountDown.style.display = 'none';
} else {
accountAdditional.style.display = 'none';
accountUp.style.display = 'none';
accountDown.style.display = 'unset';
}
});
< / script >
< script >
Chart.defaults.color = "rgba(0, 0, 0, 0.4)";
Chart.defaults.font.size = 15;
Chart.defaults.font.weight = 400;
var speedData = {
labels: [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
],
datasets: [
{
label: "Скорость",
borderColor: "#8086F9",
fill: false,
2023-09-17 12:22:14 +00:00
data: "",
2023-08-21 03:28:58 +00:00
pointStyle: false,
pointRadius: 25,
pointHoverRadius: 25,
tension: 0.1,
},
],
};
var speedOptions = {
plugins: {
legend: {
display: false,
},
},
labelStep: "3",
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
stacked: true,
grid: {
display: true,
color: "#D9D9D9",
},
ticks: {
stepSize: 10,
},
},
x: {
grid: {
display: false,
},
},
},
};
new Chart("speed", {
type: "line",
data: speedData,
options: speedOptions,
});
< / script >
2024-01-08 22:39:00 +00:00
< script >
// Получаем ссылки на элементы
const videoContainers = document.querySelectorAll('.stream-video-container video');
const popup = document.getElementById('video-popup');
const popupVideo = document.getElementById('popup-video');
const closePopup = document.getElementById('close-popup');
const popupVideoContainer = document.getElementById('popup-video-container');
const popupContainer = document.getElementById('video-popup-content');
let originalVideo = null; // Сохраняем оригинальное видео элемент
// Функция для открытия попапа с видео
function openVideoPopup(video) {
// Сохраняем оригинальное видео
originalVideo = video;
// Меняем стили видео
video.style.position = 'fixed';
video.style.top = '10%';
video.style.right = '0';
video.style.width = '90%';
video.style.height = '80%';
video.style.zIndex = '1001';
popup.style.display = 'block';
popupContainer.style.width = '100%';
popupContainer.style.height = '80%';
}
// Функция для закрытия попапа с видео
function closeVideoPopup() {
// Восстанавливаем оригинальные стили видео
if (originalVideo) {
originalVideo.style.position = '';
originalVideo.style.top = '';
originalVideo.style.left = '';
originalVideo.style.width = '';
originalVideo.style.height = '';
originalVideo.style.zIndex = '';
// Очищаем контейнер попапа
popup.style.display = 'none';
// Сбрасываем оригинальное видео
originalVideo = null;
}
}
// Добавляем обработчики событий для клика на видео и кнопку закрытия
videoContainers.forEach((video) => {
video.addEventListener('click', () => {
openVideoPopup(video);
});
});
closePopup.addEventListener('click', () => {
closeVideoPopup();
});
// Закрыть попап при клике вне е г о области
window.addEventListener('click', (event) => {
if (event.target === popup) {
closeVideoPopup();
}
});
// Закрыть попап при нажатии на клавишу Esc
window.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeVideoPopup();
}
});
< / script >
2023-08-21 03:28:58 +00:00
< / body >
< / html >