From de6eae176d03afeeaf64a57f66819cd4db25bc7f Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 3 Oct 2026 18:36:58 +0800 Subject: [PATCH] Use pointer-based monitoring wall drag for mouse and touch --- VERSION | 2 +- web/app.js | 2 +- web/monitor.js | 23 +++++++++++++++++++---- web/style.css | 1 + 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 71d6a66..c34958a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.14 +0.1.15 diff --git a/web/app.js b/web/app.js index e946265..db7be6e 100644 --- a/web/app.js +++ b/web/app.js @@ -81,7 +81,7 @@ function renderLive() { const key = ZhaoLivePlayer.key(cameras, quality); if (key === liveKey) { updateLiveStatus(cameras); return; } stopPlayers(); liveKey = key; - $('#live-grid').innerHTML = cameras.length ? cameras.map(c=>`
⠿ 拖动
◎${c.enabled ? '正在等待画面' : '设备连接已停用'}
${esc(c.name)}

${esc(siteName(c.siteId)+' · '+(c.point || '安装位置待填写'))}

${c.recordingActive ? '● 正在录像' : c.ready ? '码流已接通' : c.enabled ? '等待接通' : '已停用'}
`).join('') : (isAdmin()?empty('先接入一台摄像头','建立空间档案,再把设备添加到对应位置。',''):empty('当前范围没有可查看的摄像头','请选择已授权空间,或联系管理员配置观看权限。')); + $('#live-grid').innerHTML = cameras.length ? cameras.map(c=>`
⠿ 拖动
◎${c.enabled ? '正在等待画面' : '设备连接已停用'}
${esc(c.name)}

${esc(siteName(c.siteId)+' · '+(c.point || '安装位置待填写'))}

${c.recordingActive ? '● 正在录像' : c.ready ? '码流已接通' : c.enabled ? '等待接通' : '已停用'}
`).join('') : (isAdmin()?empty('先接入一台摄像头','建立空间档案,再把设备添加到对应位置。',''):empty('当前范围没有可查看的摄像头','请选择已授权空间,或联系管理员配置观看权限。')); for (const c of cameras.filter(c=>c.enabled)) { const video = $(`video[data-camera="${c.id}"]`); players.push(new ZhaoLivePlayer(video, video.parentElement, `/media/live/cam_${c.id}_${quality}/index.m3u8`)); diff --git a/web/monitor.js b/web/monitor.js index 1508f5e..8d38e2d 100644 --- a/web/monitor.js +++ b/web/monitor.js @@ -46,10 +46,25 @@ document.addEventListener('keydown',e=>{ if(e.key==='Escape'&&document.fullscreenElement===$('#page-live'))document.exitFullscreen().catch(()=>{}); }); setInterval(()=>{$('#wall-clock').textContent=new Date().toLocaleString('zh-CN',{hour12:false});},1000); -document.addEventListener('dragstart',e=>{const h=e.target.closest('[data-wall-drag]');if(!h)return;wallDragging=h.dataset.wallDrag;e.dataTransfer.setData('text/plain',wallDragging);e.dataTransfer.effectAllowed='move';}); -$('#live-grid').addEventListener('dragover',e=>{if(wallDragging&&$('#wall-arrange').checked)e.preventDefault();}); -$('#live-grid').addEventListener('drop',e=>{const c=e.target.closest('.camera-card');if(!c||!wallDragging)return;e.preventDefault();wallMove(wallDragging,c.querySelector('video').dataset.camera);wallDragging='';}); -document.addEventListener('dragend',()=>wallDragging=''); +let wallPointer=null; +function wallDragEnd(){wallPointer=null;wallDragging='';$$('.wall-drop-target').forEach(c=>c.classList.remove('wall-drop-target'));} +$('#live-grid').addEventListener('pointerdown',e=>{ + const handle=e.target.closest('[data-wall-drag]');if(!handle||e.button!==0||!$('#wall-arrange').checked)return; + e.preventDefault();handle.setPointerCapture(e.pointerId);wallDragging=handle.dataset.wallDrag; + wallPointer={x:e.clientX,y:e.clientY,id:e.pointerId,moved:false}; +}); +$('#live-grid').addEventListener('pointermove',e=>{ + if(!wallPointer||wallPointer.id!==e.pointerId)return; + wallPointer.moved ||= Math.hypot(e.clientX-wallPointer.x,e.clientY-wallPointer.y)>8; + $$('.wall-drop-target').forEach(c=>c.classList.remove('wall-drop-target')); + if(wallPointer.moved)document.elementFromPoint(e.clientX,e.clientY)?.closest('.camera-card')?.classList.add('wall-drop-target'); +}); +$('#live-grid').addEventListener('pointerup',e=>{ + if(!wallPointer||wallPointer.id!==e.pointerId)return; + const target=document.elementFromPoint(e.clientX,e.clientY)?.closest('.camera-card')?.querySelector('video')?.dataset.camera; + if(wallPointer.moved&&target)wallMove(wallDragging,target);wallDragEnd(); +}); +$('#live-grid').addEventListener('pointercancel',wallDragEnd); document.addEventListener('click',e=>{ const b=e.target.closest('button');if(!b)return; if(b.dataset.wallBefore||b.dataset.wallAfter){const ids=wallOrder.filter(id=>filtered().some(c=>c.id===id)),id=b.dataset.wallBefore||b.dataset.wallAfter;wallMove(id,ids[ids.indexOf(id)+(b.dataset.wallBefore?-1:1)]);} diff --git a/web/style.css b/web/style.css index 1707c26..14c8f23 100644 --- a/web/style.css +++ b/web/style.css @@ -10,3 +10,4 @@ textarea{font:inherit;color:#e3f0ef;background:#111e24;border:1px solid #3a4e55; #family-detail dl{display:grid;grid-template-columns:1fr 1fr;gap:14px 28px;margin:20px 0 26px}#family-detail dl>div{display:grid;grid-template-columns:105px 1fr;gap:10px;border-bottom:1px solid var(--line);padding-bottom:10px}#family-detail dt{font-size:12px;color:var(--muted)}#family-detail dd{margin:0;font-size:13px;overflow-wrap:anywhere}@media(max-width:1000px){#family-detail dl{grid-template-columns:1fr}} .brand-icon{width:44px;height:44px;object-fit:cover;border-radius:12px;flex-shrink:0}.wall-toolbar{display:flex;align-items:center;gap:15px;flex-wrap:wrap;margin:16px 0}.wall-toolbar select{padding:8px}.wall-paging{display:flex;align-items:center;gap:9px;color:var(--muted);font-size:12px}#wall-clock{margin-left:auto;color:var(--muted);font-size:12px}.live-grid[data-layout="1"]{grid-template-columns:1fr}.live-grid[data-layout="2"],.live-grid[data-layout="4"]{grid-template-columns:repeat(2,minmax(0,1fr))}.live-grid[data-layout="6"],.live-grid[data-layout="9"]{grid-template-columns:repeat(3,minmax(0,1fr))}.live-grid[data-layout="16"]{grid-template-columns:repeat(4,minmax(0,1fr))}.wall-reorder{display:none;padding:8px 12px;align-items:center;gap:8px}.arranging .wall-reorder{display:flex}.wall-reorder span{cursor:grab;margin-right:auto;font-size:12px;color:var(--muted)}.wall-reorder button{padding:4px 9px;font-size:11px}#page-live:fullscreen{background:#070f12;padding:12px;width:100vw;height:100dvh;display:flex;flex-direction:column;overflow:hidden}#page-live:fullscreen>.section-head,#page-live:fullscreen>#quality-note{display:none}#page-live:fullscreen .wall-toolbar{margin:0 0 10px;flex-shrink:0}#page-live:fullscreen .live-grid{flex:1;min-height:0;gap:8px;grid-template-rows:repeat(2,minmax(0,1fr))}#page-live:fullscreen .live-grid[data-layout="1"],#page-live:fullscreen .live-grid[data-layout="2"]{grid-template-rows:1fr}#page-live:fullscreen .live-grid[data-layout="9"]{grid-template-rows:repeat(3,minmax(0,1fr))}#page-live:fullscreen .live-grid[data-layout="16"]{grid-template-rows:repeat(4,minmax(0,1fr))}#page-live:fullscreen .camera-card{display:flex;flex-direction:column;min-height:0;position:relative}#page-live:fullscreen .video-panel{flex:1;min-height:0;aspect-ratio:auto}#page-live:fullscreen .camera-meta{padding:7px 10px;align-items:center}#page-live:fullscreen .camera-meta p,#page-live:fullscreen .camera-meta .badge{display:none}#page-live:fullscreen .camera-meta strong{font-size:12px}#page-live:fullscreen .camera-actions{position:absolute;bottom:34px;right:6px;padding:4px;background:#10191ddd;border-radius:6px;opacity:0}#page-live:fullscreen .camera-card:hover .camera-actions,#page-live:fullscreen .camera-card:focus-within .camera-actions{opacity:1}#page-live:fullscreen .camera-actions [data-edit-camera],#page-live:fullscreen .camera-actions [data-play-camera]{display:none}.ptz-panel{background:#1a3038;border:1px solid #41656c;border-radius:12px;padding:16px;display:flex;align-items:center;gap:22px;position:fixed;bottom:22px;right:22px;z-index:4;max-width:calc(100vw - 32px);box-shadow:0 12px 50px #0008}.ptz-panel p{font-size:12px;color:var(--muted);max-width:320px;margin:8px 0 0}.ptz-pad{display:grid;grid-template-columns:repeat(3,46px);grid-template-rows:repeat(3,40px);gap:4px}.ptz-pad button{padding:5px;font-size:17px}.ptz-pad [data-ptz-action="up"]{grid-column:2}.ptz-pad [data-ptz-action="left"]{grid-column:1;grid-row:2}.ptz-pad [data-ptz-action="stop"]{grid-column:2;grid-row:2;background:#f0bda6;font-size:12px}.ptz-pad [data-ptz-action="right"]{grid-column:3;grid-row:2}.ptz-pad [data-ptz-action="down"]{grid-column:2;grid-row:3}.family-date{border:1px solid var(--line);border-radius:8px;padding:14px;margin:0;min-width:0}.family-date legend{font-size:13px;color:#a5bec1}.family-date label{margin-bottom:10px}.family-date output{display:block;font-size:12px;line-height:1.7;color:var(--accent)}@media(max-width:760px){.wall-toolbar{gap:9px}#wall-clock{display:none}.camera-meta strong{font-size:12px}.camera-actions{flex-wrap:wrap;padding:0 8px 8px}.camera-meta{padding:9px}.ptz-panel{flex-wrap:wrap;gap:12px}.ptz-panel>div:first-child{flex:1;min-width:160px}.family-date{grid-column:1/-1}#page-live:fullscreen .camera-actions{opacity:1}.live-grid[data-layout="16"] .camera-meta strong{font-size:9px}} #page-live:fullscreen .live-grid[data-layout="auto"]{grid-template-columns:repeat(3,minmax(0,1fr))} +.wall-reorder [data-wall-drag]{touch-action:none;user-select:none;padding:5px 0}.camera-card.wall-drop-target{outline:2px solid var(--accent);outline-offset:-3px}