Compare commits

...

11 Commits

Author SHA1 Message Date
Ivan
2d0fc1a7d1
api address update 2024-02-02 11:58:13 +03:00
Ivan
12236f1fd7
fix 2024-02-02 02:21:22 +03:00
Ivan
44878e958c
testing access 2024-02-02 02:18:56 +03:00
Ivan
8ec6834485
fix db 2024-02-02 01:42:30 +03:00
Ivan
80513466d5
return normal urls 2024-02-02 01:35:53 +03:00
7643b0f957 revert dcc70199b6
revert db fix
2024-02-01 22:32:41 +00:00
Ivan
c64816adf6
remove additional domain 2024-02-01 17:22:35 +03:00
Ivan
dcc70199b6
db fix 2024-01-09 13:20:04 +03:00
Ivan
e602828d5d
live and export fix 2024-01-09 13:18:42 +03:00
Ivan
fb53bddd37
update for our registrators 2024-01-09 01:39:00 +03:00
Ivan
7f90f51499
documentation update 2023-11-08 15:47:22 +03:00
9 changed files with 575 additions and 120 deletions

View File

@ -120,7 +120,7 @@ app.post("/videos/restart", async (req, res) => {
var options = {
method: "GET",
url: `http://${process.env.VIRTUAL_HOST}/http/restart`,
url: `http://${process.env.API_ADDRESS}/http/restart`,
headers: { "Content-Type": "application/json" },
data: { video: true },
};
@ -829,7 +829,7 @@ async function live(req, res) {
// Выполняем запрос, чтобы получить все данные из таблицы registrars
const queryRegistrars = `
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number, our_registrator
FROM registrars ${!templateData.isAdmin ? "WHERE serial = ANY($1)" : ""}
ORDER BY id
`;
@ -858,6 +858,7 @@ async function live(req, res) {
ip: registrar.ip,
port: registrar.port,
number: registrar.number,
ourreg: registrar.our_registrator,
});
});
@ -2578,6 +2579,7 @@ app.get("/devices/device/:serial", async (req, res) => {
Installer: "",
Installation: "",
Description: "",
OurRegistrator: "",
};
try {
@ -2637,6 +2639,7 @@ app.get("/devices/device/:serial", async (req, res) => {
templateData.Installer = rowData.installer;
templateData.Installation = rowData.installation;
templateData.Description = rowData.description;
templateData.OurRegistrator = rowData.our_registrator;
}
const source = fs.readFileSync(
@ -2753,7 +2756,7 @@ app.post("/update-group", async (req, res) => {
async function getParameters(serial) {
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -2767,7 +2770,7 @@ async function getParameters(serial) {
await new Promise((resolve) => setTimeout(resolve, 300));
const requestResponse2 = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -2781,7 +2784,7 @@ async function getParameters(serial) {
await new Promise((resolve) => setTimeout(resolve, 300));
const requestResponse3 = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -2795,7 +2798,7 @@ async function getParameters(serial) {
await new Promise((resolve) => setTimeout(resolve, 300));
const requestResponse5 = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -2810,7 +2813,7 @@ async function getParameters(serial) {
await new Promise((resolve) => setTimeout(resolve, 300));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
return getResponse.data;
@ -2830,7 +2833,7 @@ app.post("/main-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -2844,7 +2847,7 @@ app.post("/main-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -2886,7 +2889,7 @@ app.put("/main-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -2936,7 +2939,7 @@ app.post("/ethernet-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -2950,7 +2953,7 @@ app.post("/ethernet-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -3002,7 +3005,7 @@ app.put("/ethernet-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3030,7 +3033,7 @@ app.post("/wifi-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -3044,7 +3047,7 @@ app.post("/wifi-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -3092,7 +3095,7 @@ app.put("/wifi-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3120,7 +3123,7 @@ app.post("/communication-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -3134,7 +3137,7 @@ app.post("/communication-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -3191,7 +3194,7 @@ app.put("/communication-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3219,7 +3222,7 @@ app.post("/install-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -3233,7 +3236,7 @@ app.post("/install-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -3257,7 +3260,7 @@ app.post("/ai-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -3271,7 +3274,7 @@ app.post("/ai-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -3312,7 +3315,7 @@ app.put("/ai-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3340,7 +3343,7 @@ app.post("/cameras-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const requestResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/request?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/request?serial=${serial}`,
{
headers: {
"Content-Type": "application/json",
@ -3354,7 +3357,7 @@ app.post("/cameras-parameters", async (req, res) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
const getResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/get?serial=${serial}`
`http://${process.env.API_ADDRESS}/http/parameters/get?serial=${serial}`
);
res.json(getResponse.data);
@ -3391,7 +3394,7 @@ app.put("/cameras-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3435,7 +3438,7 @@ app.put("/install-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3833,7 +3836,7 @@ app.put("/device-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3874,7 +3877,7 @@ app.put("/camera-parameters", async (req, res) => {
.send("Ошибка: lastkeepalive старше минуты или устройство не найдено.");
}
const response = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/parameters/set?serial=${serial}`,
`http://${process.env.API_ADDRESS}/http/parameters/set?serial=${serial}`,
{
data: JSON.stringify(requestBody),
headers: {
@ -3965,8 +3968,15 @@ app.post("/updatedevice", async (req, res) => {
equipmentInstaller,
equipmentInstalled,
equipmentDescription,
ourRegistrator,
} = req.body;
if (ourRegistrator == "on") {
ourRegistrator = true;
} else {
ourRegistrator = false;
}
try {
const query = `
UPDATE registrars
@ -4002,8 +4012,9 @@ app.post("/updatedevice", async (req, res) => {
installation = $29,
description = $30,
number = $31,
vin = $32
WHERE serial = $33
vin = $32,
our_registrator = $33
WHERE serial = $34
RETURNING *;
`;
@ -4040,6 +4051,7 @@ app.post("/updatedevice", async (req, res) => {
equipmentDescription,
deviceNumber,
vinNumber,
ourRegistrator,
serialNumber,
];
@ -4849,7 +4861,7 @@ async function videos(req, res) {
// Выполняем запрос, чтобы получить все данные из таблицы registrars
const queryRegistrars = `
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number, our_registrator
FROM registrars ${!templateData.isAdmin ? "WHERE serial = ANY($1)" : ""}
ORDER BY id
`;
@ -4878,6 +4890,7 @@ async function videos(req, res) {
ip: registrar.ip,
port: registrar.port,
number: registrar.number,
ourreg: registrar.our_registrator,
});
});
@ -4893,6 +4906,7 @@ async function videos(req, res) {
sim: registrar.sim,
ip: registrar.ip,
port: registrar.port,
ourreg: registrar.our_registrator,
}));
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
@ -4979,7 +4993,7 @@ async function videoExport(req, res) {
// Выполняем запрос, чтобы получить все данные из таблицы registrars
const queryRegistrars = `
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number, our_registrator
FROM registrars ${!templateData.isAdmin ? "WHERE serial = ANY($1)" : ""}
ORDER BY id
`;
@ -5008,6 +5022,7 @@ async function videoExport(req, res) {
ip: registrar.ip,
port: registrar.port,
number: registrar.number,
ourreg: registrar.our_registrator,
});
});
@ -5023,6 +5038,7 @@ async function videoExport(req, res) {
sim: registrar.sim,
ip: registrar.ip,
port: registrar.port,
ourreg: registrar.our_registrator,
}));
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
@ -5065,12 +5081,12 @@ app.get("/getData", async (req, res) => {
try {
const successResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/filelist/request?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`
`http://${process.env.API_ADDRESS}/http/filelist/request?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`
);
if (successResponse.data.SUCCESS) {
await new Promise((resolve) => setTimeout(resolve, 7000));
const dataResponse = await axios.get(
`http://${process.env.VIRTUAL_HOST}/http/filelist/get?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`
`http://${process.env.API_ADDRESS}/http/filelist/get?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`
);
if (successResponse.data.SUCCESS) {
const dataId = dataResponse.data.DATAID;

View File

@ -351,7 +351,7 @@ header img {
font-weight: 400;
opacity: 50%;
font-size: 16px;
margin: 10px 0 0 44px;
margin: 10px 44px 0 44px;
}
.whole-width button {
@ -1823,7 +1823,7 @@ input[type="datetime-local"] {
}
.speedometr .speed-bg {
z-index: 10;
z-index: 2;
position: absolute;
top: 0;
left: -20px;
@ -2164,6 +2164,7 @@ input[type="datetime-local"] {
width: 100%;
height: 100%;
position: absolute;
z-index: 2;
/* border-radius: 29px; */
}
@ -2677,6 +2678,105 @@ input[type="time"]:focus {
height: 30px !important;
}
.heart-container {
--heart-color: #8086f9;
position: relative;
width: 100%;
height: 50px;
transition: 0.3s;
display: flex;
align-items: center;
gap: 10px;
font-weight: 400;
font-size: 20px;
margin-top: 10px;
}
.heart-container .checkbox {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
z-index: 20;
cursor: pointer;
}
.heart-container .svg-container {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.heart-container .svg-outline,
.heart-container .svg-filled {
fill: var(--heart-color);
position: absolute;
}
.heart-container .svg-filled {
animation: keyframes-svg-filled 1s;
display: none;
}
.heart-container .svg-celebrate {
position: absolute;
animation: keyframes-svg-celebrate 0.5s;
animation-fill-mode: forwards;
display: none;
stroke: var(--heart-color);
fill: var(--heart-color);
stroke-width: 2px;
}
.heart-container .checkbox:checked ~ .svg-container .svg-filled {
display: block;
}
.heart-container .checkbox:checked ~ .svg-container .svg-celebrate {
display: block;
}
@keyframes keyframes-svg-filled {
0% {
transform: scale(0);
}
25% {
transform: scale(1.2);
}
50% {
transform: scale(1);
filter: brightness(1.5);
}
}
@keyframes keyframes-svg-celebrate {
0% {
transform: scale(0);
}
50% {
opacity: 1;
filter: brightness(1.5);
}
100% {
transform: scale(1.4);
opacity: 0;
display: none;
}
}
#playback-camera {
width: 500px;
margin-left: 44px;
background: #f7f7fa;
display: none;
}
@media (max-width: 1950px) {
/* при разрешении монитора до 1950 пикселей */

View File

@ -208,15 +208,6 @@
{{/if}}
</div>
<div class="permission-group">
<h2>Обновление ПО</h2>
{{#if Update}}
<img><input name="Update" type="checkbox" id="update-do" class="checkbox-input device-filter" hidden checked><label for="update-do" class="checkbox-label"><div class="checkmark"></div>Обновлять</label>
{{else}}
<img><input name="Update" type="checkbox" id="update-do" class="checkbox-input device-filter" hidden><label for="update-do" class="checkbox-label"><div class="checkmark"></div>Обновлять</label>
{{/if}}
</div>
</section>
<div style="margin-left: 44px; margin-right: 72px; width: calc(100% - 44px - 72px);" class="horizontal-line"></div>
@ -313,7 +304,6 @@
password: document.getElementById('user-password').value,
EditTransport: document.getElementById('device-edit').checked,
DeleteTransport: document.getElementById('device-delete').checked,
Update: document.getElementById('update-do').checked,
};
// Объединяем все данные в один объект

View File

@ -226,6 +226,31 @@
</div>
<div class="heart-container">
<input name="ourRegistrator" id="parameters-our-registrator" class="checkbox" type="checkbox">
<div class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" class="svg-outline" viewBox="0 0 24 24">
<path d="M17.5,1.917a6.4,6.4,0,0,0-5.5,3.3,6.4,6.4,0,0,0-5.5-3.3A6.8,6.8,0,0,0,0,8.967c0,4.547,4.786,9.513,8.8,12.88a4.974,4.974,0,0,0,6.4,0C19.214,18.48,24,13.514,24,8.967A6.8,6.8,0,0,0,17.5,1.917Zm-3.585,18.4a2.973,2.973,0,0,1-3.83,0C4.947,16.006,2,11.87,2,8.967a4.8,4.8,0,0,1,4.5-5.05A4.8,4.8,0,0,1,11,8.967a1,1,0,0,0,2,0,4.8,4.8,0,0,1,4.5-5.05A4.8,4.8,0,0,1,22,8.967C22,11.87,19.053,16.006,13.915,20.313Z">
</path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="svg-filled" viewBox="0 0 24 24">
<path d="M17.5,1.917a6.4,6.4,0,0,0-5.5,3.3,6.4,6.4,0,0,0-5.5-3.3A6.8,6.8,0,0,0,0,8.967c0,4.547,4.786,9.513,8.8,12.88a4.974,4.974,0,0,0,6.4,0C19.214,18.48,24,13.514,24,8.967A6.8,6.8,0,0,0,17.5,1.917Z">
</path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100" class="svg-celebrate">
<polygon points="10,10 20,20"></polygon>
<polygon points="10,50 20,50"></polygon>
<polygon points="20,80 30,70"></polygon>
<polygon points="90,10 80,20"></polygon>
<polygon points="90,50 80,50"></polygon>
<polygon points="80,80 70,70"></polygon>
</svg>
</div>
Является самым лучшим регистратором в мире
</div>
</div>
<div class="horizontal-line"></div>
@ -508,6 +533,8 @@
$("#parameters-device-installer").val("{{Installer}}");
$("#parameters-equipment-installed").val(formatDate("{{Installation}}"));
$("#parameters-device-description").val("{{Description}}");
$('#parameters-our-registrator').prop('checked', {{OurRegistrator}});
document.getElementById('parameters-bg').style.display = 'flex';

View File

@ -89,8 +89,24 @@
Скачать Функциональные характеристики
</div>
<div class="download-file" onclick="window.open(`http://transportsoft.ru/docs/argus/certificate.pdf`, '_blank');">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<g clip-path="url(#clip0_49_1939)">
<path d="M12 23.9883C18.5647 23.9883 24 18.5439 24 11.9941C24 5.43264 18.5529 0 11.9882 0C5.43529 0 0 5.43264 0 11.9941C0 18.5439 5.44705 23.9883 12 23.9883ZM12 21.9892C6.44705 21.9892 2.01176 17.5444 2.01176 11.9941C2.01176 6.44391 6.43529 1.99903 11.9882 1.99903C17.5411 1.99903 22 6.44391 22 11.9941C22 17.5444 17.5529 21.9892 12 21.9892ZM9.19999 18.3204H15.3412C16.6471 18.3204 17.2941 17.6502 17.2941 16.3333V11.2768H12.6353C11.8235 11.2768 11.4353 10.9006 11.4353 10.0892V5.35033H9.19999C7.90587 5.35033 7.24704 6.02059 7.24704 7.33759V16.3333C7.24704 17.662 7.90587 18.3204 9.19999 18.3204ZM12.7294 10.3244H17.2235C17.1882 10.0657 16.9999 9.80698 16.6941 9.50124L13.2118 5.95004C12.9177 5.6443 12.647 5.45616 12.3882 5.42088V9.98337C12.3882 10.2068 12.5059 10.3244 12.7294 10.3244Z" fill="#8086F9"/>
</g>
<defs>
<clipPath id="clip0_49_1939">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>
Скачать свидетельство о гос регистрации программы для ЭВМ
</div>
<h1 style="padding-bottom: 10px;">Аргус</h1>
<h3>"Автоматизированная регистрация, геопозиционирование и управление системами"</h3>
<h3>Версия 1.0.2 от 8 ноября 2023г.</h3>
<h3>© 2023 ООО “Современные Технологии”</h3>

View File

@ -163,6 +163,19 @@
</svg>
Скачать Функциональные характеристики
</div>
<div class="download-file" onclick="window.open(`http://transportsoft.ru/docs/argus/certificate.pdf`, '_blank');">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<g clip-path="url(#clip0_49_1939)">
<path d="M12 23.9883C18.5647 23.9883 24 18.5439 24 11.9941C24 5.43264 18.5529 0 11.9882 0C5.43529 0 0 5.43264 0 11.9941C0 18.5439 5.44705 23.9883 12 23.9883ZM12 21.9892C6.44705 21.9892 2.01176 17.5444 2.01176 11.9941C2.01176 6.44391 6.43529 1.99903 11.9882 1.99903C17.5411 1.99903 22 6.44391 22 11.9941C22 17.5444 17.5529 21.9892 12 21.9892ZM9.19999 18.3204H15.3412C16.6471 18.3204 17.2941 17.6502 17.2941 16.3333V11.2768H12.6353C11.8235 11.2768 11.4353 10.9006 11.4353 10.0892V5.35033H9.19999C7.90587 5.35033 7.24704 6.02059 7.24704 7.33759V16.3333C7.24704 17.662 7.90587 18.3204 9.19999 18.3204ZM12.7294 10.3244H17.2235C17.1882 10.0657 16.9999 9.80698 16.6941 9.50124L13.2118 5.95004C12.9177 5.6443 12.647 5.45616 12.3882 5.42088V9.98337C12.3882 10.2068 12.5059 10.3244 12.7294 10.3244Z" fill="#8086F9"/>
</g>
<defs>
<clipPath id="clip0_49_1939">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>
Скачать свидетельство о гос регистрации программы для ЭВМ
</div>
<h1 style="padding-bottom: 10px;">ПО для просмотра записей</h1>
<div class="download-file" onclick="window.open(`http://{{VIRTUAL_HOST}}/docs/argus-app.zip`, '_blank');">
@ -179,8 +192,11 @@
Скачать
</div>
<h1 style="padding-bottom: 10px;">Аргус</h1>
<h3>"Автоматизированная регистрация, геопозиционирование и управление системами"</h3>
<h3>Версия 1.0.2 от 8 ноября 2023г.</h3>
<h3>© 2023 ООО “Современные Технологии”</h3>

View File

@ -94,6 +94,7 @@
<div class="checkmark"></div>
</label>
<input type="number" id="channels-{{this.serial}}" value="{{this.channels}}" hidden>
<input type="text" id="ourreg-{{this.serial}}" value="{{this.ourreg}}" hidden>
<input type="radio" name="camera-serial" id="radio-{{this.serial}}" class="radio-input" value="{{this.serial}}" hidden>
<label for="radio-{{this.serial}}" class="radio-label active-{{this.status}}">
<span class="text">
@ -364,8 +365,18 @@
}
async function playNextCamerasInGroup() {
const startCamera = currentCameraGroup === 1 ? 2 : (currentCameraGroup - 1) * camerasPerGroup;
const endCamera = startCamera + camerasPerGroup - 1;
let startCamera;
let endCamera;
serial = $("input[name=camera-serial]:checked").val()
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) {
// currentCameraGroup = 1;
@ -396,33 +407,33 @@
flvPlayers.push(flvPlayer);
let hasStarted = false;
// let hasStarted = false;
const checkStarted = () => {
if (!hasStarted && videoElement.readyState >= 2) {
hasStarted = true;
console.log(`Трансляция началась для камеры ${i}`);
}
};
const checkInterval = setInterval(checkStarted, 1000);
setTimeout(() => {
clearInterval(checkInterval);
if (!hasStarted) {
console.log(`Трансляция для камеры ${i} не началась, запрашиваем повторно...`);
flvPlayer.unload();
flvPlayer.load();
flvPlayer.play();
// if (i > 0) {
// i--;
// const checkStarted = () => {
// if (!hasStarted && videoElement.readyState >= 2) {
// hasStarted = true;
// console.log(`Трансляция началась для камеры ${i}`);
// }
}
}, 3000);
// };
// const checkInterval = setInterval(checkStarted, 10000);
// setTimeout(() => {
// clearInterval(checkInterval);
// if (!hasStarted) {
// console.log(`Трансляция для камеры ${i} не началась, запрашиваем повторно...`);
// flvPlayer.unload();
// flvPlayer.load();
// flvPlayer.play();
// // if (i > 0) {
// // i--;
// // }
// }
// }, 10000);
videoElementIndex++;
await new Promise(resolve => setTimeout(resolve, 2000));
await new Promise(resolve => setTimeout(resolve, 3000));
}
}
@ -443,7 +454,7 @@
}
// Запустить воспроизведение видео при загрузке страницы
playNextCamerasInGroup();
// playNextCamerasInGroup();
</script>
@ -664,10 +675,10 @@ originalVideo = video;
// Меняем стили видео
video.style.position = 'fixed';
video.style.top = '10%';
video.style.left = '0';
video.style.width = '100%';
video.style.right = '0';
video.style.width = '90%';
video.style.height = '80%';
video.style.zIndex = '1000';
video.style.zIndex = '1001';
popup.style.display = 'block';
popupContainer.style.width = '100%';

View File

@ -127,6 +127,7 @@
<img>
<input type="number" id="channels-{{this.serial}}" value="{{this.channels}}" hidden>
<input type="radio" name="camera-serial" id="radio-{{this.serial}}" class="radio-input" value="{{this.serial}}" hidden>
<input type="text" id="ourreg-{{this.serial}}" value="{{this.ourreg}}" hidden>
<label for="radio-{{this.serial}}" class="radio-label active-{{this.status}}">
{{#if this.number}}
{{this.number}}
@ -181,6 +182,8 @@
<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>
<h3>Могут возникнуть проблемы с блокировкой всплывающих окон в браузере, при возникновении проблем проверьте что открытие новых окон из этого сайта у вас работает (обычно иконка отображается в правом верхнем углу).</h3>
</section>
</div>
@ -871,13 +874,20 @@ endVideoTimeInput.addEventListener("blur", sendPostRequest);
alert('Пожалуйста, выберите камеру из списка.');
return;
}
if (videoTimeInput.value > endVideoTimeInput.value) {
alert('Конечное время не может быть больше начального.');
return;
}
const serial = selectedDevice.value;
if ($(`#ourreg-${serial}`).val() == "true") {
} else {
if (!HasData) {
alert('Пожалуйста, выберите другой временной период.');
return;
}
if (videoTimeInput.value > endVideoTimeInput.value) {
alert('Конечное время не может быть больше начального.');
return;
}
document.getElementById("exportLoading").style.display = 'flex';
@ -898,8 +908,6 @@ endVideoTimeInput.addEventListener("blur", sendPostRequest);
const resData = await finalResponse.json();
const serial = selectedDevice.value;
const url = `http://localhost:8081/export?url=https%3A%2F%2F{{VIRTUAL_HOST}}%2Fhttp%2Fdownload.flv%3Fserial%3D${serial}%26channel%3D${channel}%26queryTime%3D${selectedDate}%26startTime%3D${startTime}%26endTime%3D${endTime}%26recordID%3D${resData.dataId}`;
document.getElementById("exportLoading").style.display = 'none';
window.open(url, '_blank');

View File

@ -8,10 +8,24 @@
<link rel="stylesheet" href="../styles/main.css" />
<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>
<style>
.stream-cameras {
width: 100%;
max-height: 450px;
display: none;
}
</style>
</head>
<body>
<div id="video-popup" class="video-popup">
<div id="video-popup-content" class="video-popup-content">
<span class="close-popup" id="close-popup">&times;</span>
<div id="popup-video-container" class="popup-video-container">
</div>
</div>
</div>
<header>
<img src="../img/argus.png">
@ -107,6 +121,7 @@
<img>
<input type="number" id="channels-{{this.serial}}" value="{{this.channels}}" hidden>
<input type="radio" name="camera-serial" id="radio-{{this.serial}}" class="radio-input" value="{{this.serial}}" hidden>
<input type="text" id="ourreg-{{this.serial}}" value="{{this.ourreg}}" hidden>
<label for="radio-{{this.serial}}" class="radio-label active-{{this.status}}">
{{#if this.number}}
{{this.number}}
@ -124,8 +139,6 @@
</section>
<section class="table" style="position: relative;">
<div class="map">
@ -135,7 +148,7 @@
<div style="background: white;" class="cameras">
<section style="border: 0;" class="whole-width">
<h1>Запустить запись с камеры</h1>
<h3>Выберите камеру, время и нажмите кнопку "Запустить запись"</h3>
<h3 id="cameras-title">Выберите камеру, время и нажмите кнопку "Запустить запись"</h3>
<form id="edit-group-form">
<div class="parameters-input">
<label for="group-id">Камера</label>
@ -161,6 +174,20 @@
<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>
<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>
</section>
</div>
@ -198,7 +225,10 @@
</div>
<div class="video-time">
<!-- <span id="from-time-label" style="margin-left: 15px; display: none;">с</span> -->
<input name="videoTime" type="time" id="video-time" step="1">
<!-- <span id="end-time-label" style="display: none;">до</span> -->
<!-- <input name="videoEndTime" type="time" id="video-end-time" step="1" style="display: none;"> -->
</div>
@ -234,6 +264,7 @@
<script src="../scripts/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.5.0/flv.min.js"></script>
<script>
@ -365,6 +396,25 @@ let HasData;
var selectedChannel = 1;
async function sendPostRequest() {
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();
}
updateCameraOptions();
document.getElementById("dataLoading").style.display = 'flex';
// Получение данных из полей ввода
@ -586,12 +636,26 @@ videoTimeInput.addEventListener("blur", sendPostRequest);
</script>
<script>
<script>
var now = new Date();
now.setHours(now.getHours() - 1);
var formattedTime = now.toISOString().substr(11, 8);
document.getElementById("video-time").value = formattedTime;
</script>
// 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>
<script>
@ -694,6 +758,7 @@ videoTimeInput.addEventListener("blur", sendPostRequest);
return formatTime(`${hours}:${minutes}:${seconds}`);
}
function playVideo() {
const channel = document.getElementById("group-id").value;
const selectedDevice = document.querySelector('input[name="camera-serial"]:checked');
@ -701,14 +766,7 @@ videoTimeInput.addEventListener("blur", sendPostRequest);
alert('Пожалуйста, выберите устройство из списка.');
return;
}
if (channel === "") {
alert('Пожалуйста, выберите камеру из списка.');
return;
}
if (!HasData) {
alert('Пожалуйста, выберите другой временной период.');
return;
}
const startTimeInput = document.getElementById('video-time');
@ -722,9 +780,148 @@ videoTimeInput.addEventListener("blur", sendPostRequest);
selectedChannel = channel;
if ($(`#ourreg-${serial}`).val() == "true") {
playNextCamerasInGroup();
} else {
if (channel === "") {
alert('Пожалуйста, выберите камеру из списка.');
return;
}
if (!HasData) {
alert('Пожалуйста, выберите другой временной период.');
return;
}
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>
<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');
const startTimeInput = document.getElementById('video-time');
// const endTimeInput = document.getElementById('video-end-time');
const selectedDateInput = document.getElementById('selectedDate');
const startTime = formatTime(startTimeInput.value);
// const endTime = formatTime(endTimeInput.value);
const selectedDate = formatDate(selectedDateInput.value);
// const endTime = addOneHourToTime(startTimeInput.value);
const serial = selectedDevice.value;
selectedChannel = channel;
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}`);
}
};
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();
}
</script>
@ -872,6 +1069,80 @@ options: speedOptions,
});
</script>
<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>
</body>