57 lines
5.6 KiB
JavaScript
57 lines
5.6 KiB
JavaScript
|
|
'use strict';
|
|||
|
|
let cameraSettingsContext=null,cameraSettingsGeneration=0;
|
|||
|
|
const videoLabels={resolution:'分辨率',fps:'帧率(帧/秒)',bitrate:'码率上限(kbps)',quality:'画质等级',gop:'关键帧间隔(帧)'};
|
|||
|
|
function clearCameraSettings(){cameraSettingsGeneration++;cameraSettingsContext=null;for(const id of ['camera-settings-info','camera-image-fields','camera-video-fields','camera-settings-status'])$('#'+id).replaceChildren();}
|
|||
|
|
function settingsInput(key,label,value,rule){
|
|||
|
|
const enumLabel=v=>key==='dayNight'?({AUTO:'自动日夜',ON:'日间(红外截止)',OFF:'夜间(红外通过)'})[v]||v:({ON:'开启',OFF:'关闭',AUTO:'自动',MANUAL:'手动'})[v]||v;
|
|||
|
|
return `<label>${esc(label)}${rule.choices?`<select name="${esc(key)}">${rule.choices.map(v=>`<option value="${esc(v)}" ${v===value?'selected':''}>${esc(enumLabel(v))}</option>`).join('')}</select>`:`<input name="${esc(key)}" type="number" value="${esc(value)}" min="${rule.min}" max="${rule.max}" step="${['fps','bitrate','gop'].includes(key)?'1':'any'}" required><small>${rule.min}–${rule.max}</small>`}</label>`;
|
|||
|
|
}
|
|||
|
|
function renderCameraSettings(data){
|
|||
|
|
const d=data.device;
|
|||
|
|
$('#camera-settings-info').innerHTML=`<dl>${[['厂商',d.Manufacturer],['型号',d.Model],['固件',d.FirmwareVersion],['镜头视频源',data.source],['码流配置',data.profile],['设备报告编码',data.video.codec]].map(([k,v])=>`<div><dt>${esc(k)}</dt><dd>${esc(v||'未提供')}</dd></div>`).join('')}</dl>`;
|
|||
|
|
$('#camera-image-fields').innerHTML=Object.entries(data.imaging).map(([k,r])=>settingsInput(k,r.label,r.value,r)).join('')||'<p class="description">设备未提供可调图像参数。</p>';
|
|||
|
|
$('#camera-video-fields').innerHTML=Object.entries(data.video.options).map(([k,r])=>settingsInput(k,videoLabels[k],data.video.values[k],r)).join('')||'<p class="description">设备未提供可调码流参数。</p>';
|
|||
|
|
$('#camera-settings-status').textContent=data.notes.join(';');
|
|||
|
|
$('#camera-image-form button[type=submit]').disabled=!Object.keys(data.imaging).length;
|
|||
|
|
$('#camera-video-form button[type=submit]').disabled=!Object.keys(data.video.options).length;
|
|||
|
|
}
|
|||
|
|
async function loadCameraSettings(){
|
|||
|
|
if(!cameraSettingsContext)return;const context=cameraSettingsContext,generation=++cameraSettingsGeneration;
|
|||
|
|
context.settings=null;context.quality=$('#camera-settings-quality').value;
|
|||
|
|
$('#camera-settings-status').textContent='正在读取设备实际参数…';
|
|||
|
|
$$('#camera-settings-dialog form button[type=submit]').forEach(b=>b.disabled=true);$('#camera-settings-reload').disabled=true;
|
|||
|
|
try{const result=await api('/api/camera/settings?'+new URLSearchParams({camera:context.id,quality:context.quality}));
|
|||
|
|
if(generation!==cameraSettingsGeneration||context!==cameraSettingsContext||!loggedIn)return;context.settings=result;renderCameraSettings(result);
|
|||
|
|
}catch(e){if(!e.stale&&generation===cameraSettingsGeneration)$('#camera-settings-status').textContent=e.message;}
|
|||
|
|
finally{if(generation===cameraSettingsGeneration)$('#camera-settings-reload').disabled=false;}
|
|||
|
|
}
|
|||
|
|
async function openCameraSettings(id){
|
|||
|
|
if(!isAdmin())return;clearCameraSettings();cameraSettingsContext={id,settings:null,quality:'main'};
|
|||
|
|
$('#camera-settings-title').textContent=(state.cameras.find(c=>c.id===id)?.name||'摄像机')+' · 参数设置';$('#camera-settings-quality').value='main';$('#camera-settings-quality').disabled=false;
|
|||
|
|
$('#camera-settings-dialog').showModal();await loadCameraSettings();
|
|||
|
|
}
|
|||
|
|
function changedCameraValues(form,section,settings){
|
|||
|
|
const rules=section==='imaging'?settings.imaging:settings.video.options,values={};
|
|||
|
|
for(const [key,rule]of Object.entries(rules)){
|
|||
|
|
const value=rule.choices?form.elements[key].value:Number(form.elements[key].value);
|
|||
|
|
if(value!==(section==='imaging'?rule.value:settings.video.values[key]))values[key]=value;
|
|||
|
|
}
|
|||
|
|
return values;
|
|||
|
|
}
|
|||
|
|
async function saveCameraSettings(form,section){
|
|||
|
|
const context=cameraSettingsContext;if(!context?.settings)return;
|
|||
|
|
const values=changedCameraValues(form,section,context.settings);if(!Object.keys(values).length){toast('参数没有变化');return;}
|
|||
|
|
const generation=++cameraSettingsGeneration;
|
|||
|
|
$$('#camera-settings-dialog form button[type=submit]').forEach(b=>b.disabled=true);$('#camera-settings-reload').disabled=true;$('#camera-settings-quality').disabled=true;
|
|||
|
|
$('#camera-settings-status').textContent='正在保存并读取设备返回值…';
|
|||
|
|
try{const result=await api('/api/camera/settings',{camera:context.id,quality:context.quality,revision:context.settings.revision,section,values});
|
|||
|
|
if(generation!==cameraSettingsGeneration||context!==cameraSettingsContext||!loggedIn)return;
|
|||
|
|
context.settings=result.settings;if(result.settings)renderCameraSettings(result.settings);$('#camera-settings-status').textContent=result.message;toast(result.message);
|
|||
|
|
}catch(e){if(!e.stale&&generation===cameraSettingsGeneration){context.settings=null;$('#camera-settings-status').textContent=e.message+'。请点击“重新读取”核对设备状态。';}}
|
|||
|
|
finally{if(generation===cameraSettingsGeneration){$('#camera-settings-reload').disabled=false;$('#camera-settings-quality').disabled=false;}}
|
|||
|
|
}
|
|||
|
|
for(const [id,section]of [['camera-image-form','imaging'],['camera-video-form','video']])$('#'+id).addEventListener('submit',e=>{e.preventDefault();saveCameraSettings(e.currentTarget,section);});
|
|||
|
|
$('#camera-settings-reload').onclick=loadCameraSettings;$('#camera-settings-quality').onchange=loadCameraSettings;
|
|||
|
|
$('#camera-settings-dialog').addEventListener('close',clearCameraSettings);
|
|||
|
|
document.addEventListener('click',e=>{const b=e.target.closest('[data-camera-settings]');if(b)openCameraSettings(b.dataset.cameraSettings);});
|