|
|
|
const apiEndpoint = '/api/channel/list';
|
|
|
|
const rowsPerPage = 10;
|
|
|
|
//算法配置窗口部分控件
|
|
|
|
const searchEndpoint = '/api/channel/select';
|
|
|
|
const canvas = document.getElementById('myCanvas');
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
const backgroundCanvas = document.getElementById('backgroundCanvas');
|
|
|
|
const backgroundCtx = backgroundCanvas.getContext('2d');
|
|
|
|
const img = new Image();
|
|
|
|
const tbody = document.getElementById('schedule-body');//布防计划
|
|
|
|
|
|
|
|
let currentPage = 1;
|
|
|
|
let channelData = [];
|
|
|
|
let channelData_bak = [];
|
|
|
|
let areaData = ["请选择"];
|
|
|
|
let currentEditingRow = null;
|
|
|
|
let cid_schedule = "-1";
|
|
|
|
let m_polygon = "";
|
|
|
|
let check_area = 0;
|
|
|
|
let draw_status = false; //是否是绘制状态,处于绘制状态才能开始绘制
|
|
|
|
let b_img = false; //有没有加载图片成功,如果没有初始化的时候就不绘制线条了。
|
|
|
|
let points = []; //检测区域的点坐标数组
|
|
|
|
//布防计划
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
fetchChannelData(); //初始化通道管理页面元素数据
|
|
|
|
|
|
|
|
document.getElementById('searchButton').addEventListener('click', function () {
|
|
|
|
performSearch();
|
|
|
|
});
|
|
|
|
//新增通道模块--保存按钮
|
|
|
|
document.getElementById('saveButton').addEventListener('click', function () {
|
|
|
|
addChannel(1);
|
|
|
|
});
|
|
|
|
//修改通道模块--保存按钮
|
|
|
|
document.getElementById('saveButton_cc').addEventListener('click', function () {
|
|
|
|
addChannel(2);
|
|
|
|
});
|
|
|
|
//算法配置模块--取消按钮
|
|
|
|
document.getElementById('cancelButton_mx').addEventListener('click', function () {
|
|
|
|
close_mx_model();
|
|
|
|
});
|
|
|
|
//保存算法配置--保存按钮
|
|
|
|
document.getElementById('saveButton_mx').addEventListener('click', function () {
|
|
|
|
save_mx_model();
|
|
|
|
});
|
|
|
|
//开始绘制区域按钮
|
|
|
|
document.getElementById('but_hzqy').addEventListener('click', function () {
|
|
|
|
startDraw();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
//添加和修改通道 1--新增,2--修改
|
|
|
|
function addChannel(itype) {
|
|
|
|
let area;
|
|
|
|
let cName;
|
|
|
|
let Rtsp;
|
|
|
|
let cid;
|
|
|
|
const spinnerOverlay = document.getElementById("spinnerOverlay");
|
|
|
|
let saveButton = null;
|
|
|
|
let CNameInput = null;
|
|
|
|
let RTSPInput = null;
|
|
|
|
|
|
|
|
if(itype ==1){
|
|
|
|
saveButton = document.getElementById('saveButton');
|
|
|
|
CNameInput = document.getElementById('CNameInput');
|
|
|
|
RTSPInput = document.getElementById('RTSPInput');
|
|
|
|
area = document.getElementById('areaSelect_M').value;
|
|
|
|
cid = -1
|
|
|
|
}
|
|
|
|
else if(itype ==2){
|
|
|
|
saveButton = document.getElementById('saveButton_cc');
|
|
|
|
CNameInput = document.getElementById('CNameInput_cc');
|
|
|
|
RTSPInput = document.getElementById('RTSPInput_cc');
|
|
|
|
area = document.getElementById('areaSelect_CC').value;
|
|
|
|
cid = currentEditingRow.cells[0].innerText;
|
|
|
|
}
|
|
|
|
console.log("点击了保存按钮");
|
|
|
|
cName = CNameInput.value.trim();
|
|
|
|
Rtsp = RTSPInput.value.trim();
|
|
|
|
if(area === "请选择"){
|
|
|
|
alert('请选择所属区域');
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (cName && Rtsp) {
|
|
|
|
saveButton.disabled = true;
|
|
|
|
//发送视频链接接口
|
|
|
|
const url = '/api/channel/add';
|
|
|
|
const data = {"area":area,"cName":cName,"Rtsp":Rtsp,"cid":cid};
|
|
|
|
// 显示 Spinners
|
|
|
|
spinnerOverlay.style.display = "flex";
|
|
|
|
// 发送 POST 请求
|
|
|
|
fetch(url, {
|
|
|
|
method: 'POST', // 指定请求方法为 POST
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json' // 设置请求头,告诉服务器请求体的数据类型为 JSON
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data) // 将 JavaScript 对象转换为 JSON 字符串
|
|
|
|
})
|
|
|
|
.then(response => response.json()) // 将响应解析为 JSON
|
|
|
|
.then(data => {
|
|
|
|
const istatus = data.status;
|
|
|
|
saveButton.disabled = false;
|
|
|
|
alert(data.msg); // 使用 Modal 显示消息
|
|
|
|
if(istatus == 1){
|
|
|
|
//刷新列表
|
|
|
|
fetchChannelData();
|
|
|
|
if(itype ==1){
|
|
|
|
//添加通道成功
|
|
|
|
$('#channelModal').modal('hide');
|
|
|
|
}
|
|
|
|
else if(itype==2){
|
|
|
|
//修改通道成功
|
|
|
|
currentEditingRow = null;
|
|
|
|
$('#ChangeC').modal('hide');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
alert(`Error: ${error.message}`); // 使用 Modal 显示错误信息
|
|
|
|
// 启用保存按钮
|
|
|
|
saveButton.disabled = false;
|
|
|
|
return;
|
|
|
|
})
|
|
|
|
.finally(()=>{
|
|
|
|
// 隐藏 Spinners
|
|
|
|
spinnerOverlay.style.display = "none";
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
alert('通道名称和RTSP地址不能为空');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//初始化通道管理页面元素数据
|
|
|
|
async function fetchChannelData() { //获取通道相关信息(/api/channel/list),刷新通道表格控件数据
|
|
|
|
try {
|
|
|
|
const response = await fetch(apiEndpoint);
|
|
|
|
channelData = await response.json();
|
|
|
|
channelData_bak = channelData;
|
|
|
|
|
|
|
|
url = "/api/channel/area/list"
|
|
|
|
area_response = await fetch(url);
|
|
|
|
areaDatas = await area_response.json();
|
|
|
|
areaData = ["请选择"]; //清空下
|
|
|
|
areaDatas.forEach((area) => {
|
|
|
|
areaData.push(area.area_name)
|
|
|
|
});
|
|
|
|
|
|
|
|
renderTable(); //刷新表格
|
|
|
|
renderPagination(); //刷新分页元素
|
|
|
|
renderAreaOptions(); //所属区域下来框
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error fetching channel data:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//刷新表单页面数据
|
|
|
|
function renderTable() {
|
|
|
|
const tableBody = document.getElementById('table-body');
|
|
|
|
tableBody.innerHTML = '';
|
|
|
|
|
|
|
|
const start = (currentPage - 1) * rowsPerPage;
|
|
|
|
const end = start + rowsPerPage;
|
|
|
|
const pageData = channelData.slice(start, end);
|
|
|
|
const surplus_count = rowsPerPage - pageData.length;
|
|
|
|
|
|
|
|
pageData.forEach((channel) => {
|
|
|
|
// if(area_name!==channel.area_name){ //这里要求区域名称一样的要在一起
|
|
|
|
// area_name = channel.area_name;
|
|
|
|
// areaData.push(area_name);
|
|
|
|
// }
|
|
|
|
const row = document.createElement('tr');
|
|
|
|
row.innerHTML = `
|
|
|
|
<td>${channel.ID}</td>
|
|
|
|
<td>${channel.area_name}</td>
|
|
|
|
<td>${channel.channel_name}</td>
|
|
|
|
<td>${channel.ulr}</td>
|
|
|
|
<td>${channel.model_name}</td>
|
|
|
|
<td>
|
|
|
|
<button class="btn btn-primary btn-sm modify-btn">修改</button>
|
|
|
|
<button class="btn btn-secondary btn-sm algorithm-btn">算法</button>
|
|
|
|
<button class="btn btn-danger btn-sm delete-btn">删除</button>
|
|
|
|
</td>
|
|
|
|
`;
|
|
|
|
tableBody.appendChild(row);
|
|
|
|
row.querySelector('.modify-btn').addEventListener('click', () => modifyChannel(row));
|
|
|
|
row.querySelector('.algorithm-btn').addEventListener('click', () => configureAlgorithm(row));
|
|
|
|
row.querySelector('.delete-btn').addEventListener('click', () => deleteChannel(row));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//关键字查询数据
|
|
|
|
async function performSearch() {
|
|
|
|
try {
|
|
|
|
const area = document.getElementById('areaSelect').value;
|
|
|
|
const channelName = document.getElementById('channelNameInput').value;
|
|
|
|
if(area === "请选择" && channelName===""){
|
|
|
|
channelData = channelData_bak;
|
|
|
|
}
|
|
|
|
else if(area === "请选择"){
|
|
|
|
channelData = [];
|
|
|
|
channelData_bak.forEach((channel) => {
|
|
|
|
if(channelName === channel.channel_name){
|
|
|
|
channelData.push(channel);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else if(channelName === ""){
|
|
|
|
channelData = [];
|
|
|
|
channelData_bak.forEach((channel) => {
|
|
|
|
if(area === channel.area_name){
|
|
|
|
channelData.push(channel);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
channelData = [];
|
|
|
|
channelData_bak.forEach((channel) => {
|
|
|
|
if(area === channel.area_name && channelName === channel.channel_name){
|
|
|
|
channelData.push(channel);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
// 渲染表格和分页控件
|
|
|
|
currentPage = 1; // 重置当前页为第一页
|
|
|
|
renderTable();
|
|
|
|
renderPagination();
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error performing search:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//点击修改按钮,显示修改通道信息模块 --只是显示
|
|
|
|
function modifyChannel(row) {
|
|
|
|
// const cid = row.cells[0].innerText;
|
|
|
|
const areaName = row.cells[1].innerText;
|
|
|
|
const channelName = row.cells[2].innerText;
|
|
|
|
const url = row.cells[3].innerText;
|
|
|
|
|
|
|
|
const area = document.getElementById('areaSelect_CC');
|
|
|
|
const CName = document.getElementById('CNameInput_cc');
|
|
|
|
const RTSP = document.getElementById('RTSPInput_cc');
|
|
|
|
|
|
|
|
for(let i=0;i< area.options.length;i++){
|
|
|
|
if(area.options[i].value === areaName){
|
|
|
|
area.options[i].selected = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CName.value = channelName;
|
|
|
|
RTSP.value = url;
|
|
|
|
|
|
|
|
currentEditingRow = row;
|
|
|
|
$('#ChangeC').modal('show');
|
|
|
|
}
|
|
|
|
|
|
|
|
//点击算法按钮,显示算法配置模块 --只是显示
|
|
|
|
function configureAlgorithm(row) {
|
|
|
|
//获取当前行信息
|
|
|
|
currentEditingRow = row;
|
|
|
|
const cid = row.cells[0].innerText;
|
|
|
|
//清除数据,若需要的话
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height); //清除左侧绘画和画线信息
|
|
|
|
tbody.innerHTML = ''; //清空布防控件数据
|
|
|
|
points = []; //清空绘制检测区域
|
|
|
|
draw_status = false;
|
|
|
|
b_img = false;
|
|
|
|
document.getElementById('but_hzqy').textContent = "绘制区域";
|
|
|
|
//开始初始化算法管理模块
|
|
|
|
show_channel_model_schedule(cid); //获取并显示结构化数据
|
|
|
|
show_channel_img(cid); //获取并显示一帧图片 -- 获取不到图片就是黑画面 --并要绘制检测区域
|
|
|
|
|
|
|
|
//显示窗口
|
|
|
|
$('#MX_M').modal('show');
|
|
|
|
}
|
|
|
|
|
|
|
|
//获取一帧图片
|
|
|
|
function show_channel_img(cid){
|
|
|
|
const data = {"cid":cid};
|
|
|
|
fetch('/api/channel/img', {
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data)
|
|
|
|
})
|
|
|
|
.then(response => response.json())
|
|
|
|
.then(data => {
|
|
|
|
if (data.image) {
|
|
|
|
b_img = true;
|
|
|
|
img.src = 'data:image/jpeg;base64,' + data.image;
|
|
|
|
} else {
|
|
|
|
console.error('Error:', data.error);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(error => console.error('Error:', error));
|
|
|
|
}
|
|
|
|
|
|
|
|
//图片加载事项
|
|
|
|
img.onload = () => { //清除、画图和画线应该分开
|
|
|
|
// 设置画布宽高
|
|
|
|
backgroundCanvas.width = canvas.width = img.width;
|
|
|
|
backgroundCanvas.height = canvas.height = img.height;
|
|
|
|
// 将图片绘制到背景画布上
|
|
|
|
backgroundCtx.drawImage(img, 0, 0, img.width, img.height);
|
|
|
|
drawLines();
|
|
|
|
// 将背景画布的内容复制到前台画布上
|
|
|
|
//ctx.drawImage(backgroundCanvas, 0, 0, canvas.width, canvas.height); //绘制画面
|
|
|
|
};
|
|
|
|
|
|
|
|
//开始和重新绘制
|
|
|
|
function startDraw(){
|
|
|
|
if(!document.getElementById('zdjc').checked){
|
|
|
|
alert("请先选择指定区域!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let but = document.getElementById('but_hzqy');
|
|
|
|
if(!draw_status){//开始绘制
|
|
|
|
if(points.length >0){
|
|
|
|
if (confirm('开始绘制将清除未提交保存的绘制数据,是否继续?')) {
|
|
|
|
draw_status = true;
|
|
|
|
points = [];
|
|
|
|
//按钮文字调整为结束绘制
|
|
|
|
but.textContent = '结 束 绘 制';
|
|
|
|
// 清除前台画布
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// 将背景画布的内容复制到前台画布上
|
|
|
|
ctx.drawImage(backgroundCanvas, 0, 0, canvas.width, canvas.height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
draw_status = true;
|
|
|
|
but.textContent = '结束绘制';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{//结束绘制
|
|
|
|
draw_status = false;
|
|
|
|
but.textContent = '绘制区域';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//单选按钮点击事件处理
|
|
|
|
function handleRadioClick(event) {
|
|
|
|
const selectedRadio = event.target;
|
|
|
|
console.log('Selected Radio:', selectedRadio.id);
|
|
|
|
// 根据选中的单选按钮执行相应操作
|
|
|
|
if (selectedRadio.id === 'qjjc') {
|
|
|
|
if(draw_status){
|
|
|
|
alert("请先结束绘制后,再切换检测方案!");
|
|
|
|
document.getElementById('zdjc').checked = true;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
// 处理全画面生效的逻辑
|
|
|
|
if(points.length>0){
|
|
|
|
if (!confirm('切换到全画面生效,将清除已绘制的区域信息,是否切换?')) {
|
|
|
|
document.getElementById('zdjc').checked = true;
|
|
|
|
}else{
|
|
|
|
points = [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//console.log('全画面生效');
|
|
|
|
} else if (selectedRadio.id === 'zdjc') {
|
|
|
|
// 处理指定区域的逻辑
|
|
|
|
console.log('指定区域');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 鼠标点击事件处理--动态绘图
|
|
|
|
canvas.addEventListener('click', (event) => {
|
|
|
|
if(draw_status){
|
|
|
|
const rect = canvas.getBoundingClientRect();
|
|
|
|
const scaleX = canvas.width / rect.width;
|
|
|
|
const scaleY = canvas.height / rect.height;
|
|
|
|
|
|
|
|
// 获取鼠标相对于canvas的位置
|
|
|
|
const x = (event.clientX - rect.left) * scaleX;
|
|
|
|
const y = (event.clientY - rect.top) * scaleY;
|
|
|
|
points.push({ x, y });
|
|
|
|
console.log(points);
|
|
|
|
//绘制线条
|
|
|
|
drawLines();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// 绘制区域,各点连接
|
|
|
|
function drawLines() {
|
|
|
|
if(b_img){
|
|
|
|
// 清除前台画布
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// 将背景画布的内容复制到前台画布上
|
|
|
|
ctx.drawImage(backgroundCanvas, 0, 0, canvas.width, canvas.height);
|
|
|
|
|
|
|
|
// 绘制点和线
|
|
|
|
ctx.strokeStyle = 'red';
|
|
|
|
ctx.lineWidth = 2;
|
|
|
|
|
|
|
|
if (points.length > 0) {
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.moveTo(points[0].x, points[0].y);
|
|
|
|
|
|
|
|
for (let i = 1; i < points.length; i++) {
|
|
|
|
ctx.lineTo(points[i].x, points[i].y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 连接最后一个点到起点
|
|
|
|
ctx.lineTo(points[0].x, points[0].y);
|
|
|
|
ctx.stroke();
|
|
|
|
}
|
|
|
|
|
|
|
|
points.forEach(point => {
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.arc(point.x, point.y, 5, 0, Math.PI * 2);
|
|
|
|
ctx.fillStyle = 'red';
|
|
|
|
ctx.fill();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//获取并显示该通道相关算法的结构化数据 --- 这里用GET会更加贴切一些
|
|
|
|
function show_channel_model_schedule(cid){
|
|
|
|
//发送视频链接接口
|
|
|
|
const url = '/api/channel/C2M';
|
|
|
|
const data = {"cid":cid};
|
|
|
|
// 发送 POST 请求
|
|
|
|
fetch(url, {
|
|
|
|
method: 'POST', // 指定请求方法为 POST
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json' // 设置请求头,告诉服务器请求体的数据类型为 JSON
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data) // 将 JavaScript 对象转换为 JSON 字符串
|
|
|
|
})
|
|
|
|
.then(response => response.json()) // 将响应解析为 JSON
|
|
|
|
.then(data => {
|
|
|
|
const m_datas = data.m_datas; //算法清单
|
|
|
|
const c2m_data = data.c2m_data; //该通道管理算法的相关数据,会有空的情况
|
|
|
|
const schedule = data.schedule; //布防计划
|
|
|
|
//console.log("m_datas--",m_datas);
|
|
|
|
//console.log("c2m_data--",c2m_data);
|
|
|
|
//console.log("schedule--",schedule);
|
|
|
|
//配置算法下拉清单
|
|
|
|
select_datas = ["请选择"];
|
|
|
|
m_datas.forEach(option => {
|
|
|
|
select_datas.push(option.model_name);
|
|
|
|
});
|
|
|
|
set_select_data("model_select",select_datas);
|
|
|
|
select_str = currentEditingRow.cells[4].innerText;
|
|
|
|
//检测区域
|
|
|
|
if(c2m_data.length >0){
|
|
|
|
model_id = c2m_data[0].model_id;
|
|
|
|
model_name = currentEditingRow.cells[4].innerText;
|
|
|
|
set_select_selct("model_select",model_name);
|
|
|
|
check_area = c2m_data[0].check_area
|
|
|
|
if( check_area == 0){ //全画面生效
|
|
|
|
document.getElementById('qjjc').checked = true;
|
|
|
|
m_polygon = "";
|
|
|
|
}
|
|
|
|
else{//指定区域
|
|
|
|
document.getElementById('zdjc').checked = true;
|
|
|
|
m_polygon = c2m_data[0].polygon;
|
|
|
|
console.log("m_polygon--",m_polygon);
|
|
|
|
if(m_polygon !== ""){ //指定区域了,一般是会有数据的。
|
|
|
|
const coords = parseCoordStr(m_polygon);
|
|
|
|
points = coords;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//阈值
|
|
|
|
document.getElementById('zxyz').value = c2m_data[0].conf_thres
|
|
|
|
document.getElementById('iouyz').value = c2m_data[0].iou_thres
|
|
|
|
}
|
|
|
|
|
|
|
|
//布防计划
|
|
|
|
const days = ['一', '二', '三', '四', '五', '六','日'];
|
|
|
|
const num_days=['0','1','2','3','4','5','6']
|
|
|
|
days.forEach((day, dayIndex) => {
|
|
|
|
const row = document.createElement('tr');
|
|
|
|
const dayCell = document.createElement('th');
|
|
|
|
dayCell.textContent = day;
|
|
|
|
row.appendChild(dayCell);
|
|
|
|
num_day = num_days[dayIndex]
|
|
|
|
for (let hour = 0; hour < 24; hour++) {
|
|
|
|
const cell = document.createElement('td');
|
|
|
|
if(schedule.length >0){
|
|
|
|
const status = schedule.find(item => item.day === num_day && item.hour === hour);
|
|
|
|
if (status && status.status === 1) {
|
|
|
|
cell.classList.add('blocked');
|
|
|
|
} else {
|
|
|
|
cell.classList.add('allowed');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
cell.classList.add('blocked');
|
|
|
|
}
|
|
|
|
row.appendChild(cell);
|
|
|
|
|
|
|
|
cell.addEventListener('click', () => {
|
|
|
|
if (cell.classList.contains('blocked')) {
|
|
|
|
cell.classList.remove('blocked');
|
|
|
|
cell.classList.add('allowed');
|
|
|
|
// Update status in the database
|
|
|
|
//updateStatus(day, hour, 0);
|
|
|
|
} else {
|
|
|
|
cell.classList.remove('allowed');
|
|
|
|
cell.classList.add('blocked');
|
|
|
|
// Update status in the database
|
|
|
|
//updateStatus(day, hour, 1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
tbody.appendChild(row);
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
alert(`Error: ${error.message}`); // 使用 Modal 显示错误信息
|
|
|
|
return;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// 将字符串转换为数组
|
|
|
|
function parseCoordStr(str) {
|
|
|
|
return str.match(/\(([^)]+)\)/g).map(pair => {
|
|
|
|
const [x, y] = pair.replace(/[()]/g, '').split(',').map(Number);
|
|
|
|
return { x, y };
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
//关闭算法配置窗口
|
|
|
|
function close_mx_model(){
|
|
|
|
if (confirm('确定退出窗口吗?未保存的修改将丢失!')) {
|
|
|
|
$('#MX_M').modal('hide');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//保存算法配置窗口数据
|
|
|
|
function save_mx_model(){
|
|
|
|
let model_name; //算法名称
|
|
|
|
let check_area; //检测区域标识 0-全局,1-指定范围
|
|
|
|
let polygon_str; //具体的检测区域
|
|
|
|
let conf_thres; //置信阈值
|
|
|
|
let iou_thres; //iou阈值
|
|
|
|
let schedule; //布防计划
|
|
|
|
const saveButton = document.getElementById('saveButton_mx');
|
|
|
|
saveButton.disabled = true; //不可点击状态
|
|
|
|
//配置算法
|
|
|
|
model_name = document.getElementById("model_select").value;
|
|
|
|
//检测区域
|
|
|
|
if(document.getElementById('zdjc').checked){
|
|
|
|
check_area = 1;
|
|
|
|
console.log("points--",points);
|
|
|
|
if (points.length > 0){
|
|
|
|
const formattedArray = points.map(point => `(${point.x},${point.y})`);
|
|
|
|
polygon_str = `[${formattedArray.join(',')}]`;
|
|
|
|
}else{
|
|
|
|
polygon_str = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
}else{
|
|
|
|
check_area = 0;
|
|
|
|
polygon_str = "";
|
|
|
|
}
|
|
|
|
//置信阈值和IOU阈值
|
|
|
|
conf_thres = getInputValueAsFloat('zxyz');
|
|
|
|
iou_thres = getInputValueAsFloat('iouyz');
|
|
|
|
//验证数据
|
|
|
|
if(model_name !== "请选择"){
|
|
|
|
console.log(model_name);
|
|
|
|
if(conf_thres <= 0 || conf_thres>=1 || iou_thres <= 0 || iou_thres>=1){
|
|
|
|
alert("阈值的有效范围是大于0,小于1;请输入正确的阈值(默认可0.5)。");
|
|
|
|
saveButton.disabled = false; //不可点击状态
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//布防计划
|
|
|
|
// 定义一个对象来存储数据
|
|
|
|
const scheduleData = {
|
|
|
|
'0': Array(24).fill(0),
|
|
|
|
'1': Array(24).fill(0),
|
|
|
|
'2': Array(24).fill(0),
|
|
|
|
'3': Array(24).fill(0),
|
|
|
|
'4': Array(24).fill(0),
|
|
|
|
'5': Array(24).fill(0),
|
|
|
|
'6': Array(24).fill(0)
|
|
|
|
};
|
|
|
|
// 遍历 tbody 的每一行
|
|
|
|
[...tbody.children].forEach((row, dayIndex) => {
|
|
|
|
// 获取当前行的所有单元格
|
|
|
|
const cells = row.getElementsByTagName('td');
|
|
|
|
|
|
|
|
// 遍历每一个单元格
|
|
|
|
for (let hour = 0; hour < cells.length; hour++) {
|
|
|
|
// 检查单元格的 class 是否包含 'blocked'
|
|
|
|
if (cells[hour].classList.contains('blocked')) {
|
|
|
|
// 将对应的 scheduleData 位置设置为 1
|
|
|
|
scheduleData[dayIndex][hour] = 1;
|
|
|
|
} else {
|
|
|
|
// 将对应的 scheduleData 位置设置为 0
|
|
|
|
scheduleData[dayIndex][hour] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// 将 scheduleData 对象转换为 JSON 字符串
|
|
|
|
const scheduleData_json = JSON.stringify(scheduleData);
|
|
|
|
//提交到服务器
|
|
|
|
// console.log("model_name--",model_name);
|
|
|
|
// console.log("check_area--",check_area);
|
|
|
|
// console.log("polygon_str--",polygon_str);
|
|
|
|
// console.log("iou_thres--",iou_thres);
|
|
|
|
// console.log("conf_thres--",conf_thres);
|
|
|
|
// console.log("schedule-- ",scheduleData_json);
|
|
|
|
cid = currentEditingRow.cells[0].innerText;
|
|
|
|
const url = '/api/channel/chanegeC2M';
|
|
|
|
const data = {"model_name":model_name,"check_area":check_area,"polygon_str":polygon_str,"iou_thres":iou_thres,
|
|
|
|
"conf_thres":conf_thres,"schedule":scheduleData_json,"cid":cid};
|
|
|
|
// 发送 POST 请求
|
|
|
|
fetch(url, {
|
|
|
|
method: 'POST', // 指定请求方法为 POST
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json' // 设置请求头,告诉服务器请求体的数据类型为 JSON
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data) // 将 JavaScript 对象转换为 JSON 字符串
|
|
|
|
})
|
|
|
|
.then(response => response.json()) // 将响应解析为 JSON
|
|
|
|
.then(data => {
|
|
|
|
const istatus = data.status;
|
|
|
|
if(istatus === 0){
|
|
|
|
alert(data.msg); // 使用 Modal 显示消息
|
|
|
|
// 启用保存按钮
|
|
|
|
saveButton.disabled = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
// 启用保存按钮
|
|
|
|
saveButton.disabled = false;
|
|
|
|
//刷新列表
|
|
|
|
fetchChannelData();
|
|
|
|
//$('#MX_M').modal('hide');
|
|
|
|
alert("修改成功!");
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
alert(`Error: ${error.message}`);
|
|
|
|
// 启用保存按钮
|
|
|
|
saveButton.disabled = false;
|
|
|
|
return;
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//删除通道
|
|
|
|
function deleteChannel(row) {
|
|
|
|
if (confirm('确定删除此通道吗?')) {
|
|
|
|
cid = row.cells[0].innerText;
|
|
|
|
//发送视频链接接口
|
|
|
|
const url = '/api/channel/del';
|
|
|
|
const data = {"cid":cid};
|
|
|
|
// 发送 POST 请求
|
|
|
|
fetch(url, {
|
|
|
|
method: 'POST', // 指定请求方法为 POST
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json' // 设置请求头,告诉服务器请求体的数据类型为 JSON
|
|
|
|
},
|
|
|
|
body: JSON.stringify(data) // 将 JavaScript 对象转换为 JSON 字符串
|
|
|
|
})
|
|
|
|
.then(response => response.json()) // 将响应解析为 JSON
|
|
|
|
.then(data => {
|
|
|
|
const istatus = data.status;
|
|
|
|
if(istatus === 0){
|
|
|
|
alert(data.msg); // 使用 Modal 显示消息
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
//刷新列表
|
|
|
|
row.remove();
|
|
|
|
alert("删除通道成功!");
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
alert(`Error: ${error.message}`); // 使用 Modal 显示错误信息
|
|
|
|
return;
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//刷新分页标签
|
|
|
|
function renderPagination() {
|
|
|
|
const pagination = document.getElementById('pagination');
|
|
|
|
pagination.innerHTML = '';
|
|
|
|
|
|
|
|
const totalPages = Math.ceil(channelData.length / rowsPerPage);
|
|
|
|
for (let i = 1; i <= totalPages; i++) {
|
|
|
|
const pageItem = document.createElement('li');
|
|
|
|
pageItem.className = 'page-item' + (i === currentPage ? ' active' : '');
|
|
|
|
pageItem.innerHTML = `<a class="page-link" href="#">${i}</a>`;
|
|
|
|
pageItem.addEventListener('click', (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
currentPage = i;
|
|
|
|
renderTable();
|
|
|
|
renderPagination();
|
|
|
|
});
|
|
|
|
pagination.appendChild(pageItem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//刷新区域下拉控件
|
|
|
|
function renderAreaOptions() {
|
|
|
|
const areaSelect = document.getElementById('areaSelect');
|
|
|
|
const areaSelect_M = document.getElementById('areaSelect_M')
|
|
|
|
const areaSelect_CC = document.getElementById('areaSelect_CC')
|
|
|
|
//先清空
|
|
|
|
areaSelect.innerHTML = '';
|
|
|
|
areaSelect_M.innerHTML = '';
|
|
|
|
areaSelect_CC.innerHTML = '';
|
|
|
|
//再添加
|
|
|
|
areaData.forEach(option => {
|
|
|
|
const optionElement = document.createElement('option');
|
|
|
|
optionElement.textContent = option;
|
|
|
|
areaSelect.appendChild(optionElement);
|
|
|
|
|
|
|
|
const optionElement_m = document.createElement('option');
|
|
|
|
optionElement_m.textContent = option;
|
|
|
|
areaSelect_M.appendChild(optionElement_m);
|
|
|
|
|
|
|
|
const optionElement_cc = document.createElement('option');
|
|
|
|
optionElement_cc.textContent = option;
|
|
|
|
areaSelect_CC.appendChild(optionElement_cc);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|