fix(host): 起浮窗不再经 cmd/start(那个黑控制台窗口);feat(shell): 相机按钮一键切换截图隐藏 + 标准齿轮设置图标

- 黑窗根因:spawnShell 用 cmd /c start 跑 .cmd,start 会新建控制台,批处理里的中文还被按 GBK 解析成乱码报错。
  改成 spawn('powershell.exe', [-WindowStyle Hidden -File ...]) detached + windowsHide,无窗启动
- 标题栏新增相机按钮:一键切换『截图时隐藏本窗』(高亮=隐藏生效),设置面板里那项同步;
  开发期要截图给别人看,点一下就可见
- 设置图标从'小太阳'换成标准齿轮
This commit is contained in:
2026-09-27 17:07:35 +08:00
parent 7d1417fa1c
commit cb57f75577
2 changed files with 19 additions and 17 deletions
+8 -14
View File
@@ -613,22 +613,16 @@ export function apply(ctx, config) {
} }
async function spawnShell() { async function spawnShell() {
const cmd = shellPath() // 直接起 powershell(隐藏窗口)。**不要**走 `cmd /c start`:那会弹出一个黑色控制台窗口
if (!fs.existsSync(cmd)) return { ok: false, error: `launcher not found: ${cmd}` } // (用户已经看到过:标题 C:\WINDOWS\system32\cmd.exe,且批处理里的中文被 GBK 解析成乱码报错)。
try { const ps1 = path.join(REPO, 'shell', 'float-window.ps1')
const shell = ctx.get('shell') if (!fs.existsSync(ps1)) return { ok: false, error: `shell script not found: ${ps1}` }
const sp = ctx.get('sandboxPolicy')
const policy = sp?.resolve?.({ mode: 'danger-full-access' })
if (shell?.resolve && shell?.run) {
const spec = shell.resolve({ command: `cmd /c start "" "${cmd}"`, ...(policy ? { sandboxPolicy: policy } : {}) })
await shell.run(spec)
return { ok: true, via: 'ctx.shell' }
}
} catch (e) { log('ctx.shell launch failed, fallback to spawn:', String(e?.message || e)) }
try { try {
const { spawn } = await import('node:child_process') const { spawn } = await import('node:child_process')
spawn('cmd', ['/c', 'start', '', cmd], { detached: true, stdio: 'ignore', windowsHide: true }).unref() spawn('powershell.exe',
return { ok: true, via: 'spawn' } ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-WindowStyle', 'Hidden', '-File', ps1],
{ detached: true, stdio: 'ignore', windowsHide: true }).unref()
return { ok: true, via: 'spawn powershell (hidden)' }
} catch (e) { return { ok: false, error: String(e?.message || e) } } } catch (e) { return { ok: false, error: String(e?.message || e) } }
} }
+11 -3
View File
@@ -568,10 +568,16 @@
<path d="M4 9V5h4M20 15v4h-4M20 9V5h-4M4 15v4h4" /> <path d="M4 9V5h4M20 15v4h-4M20 9V5h-4M4 15v4h4" />
</svg> </svg>
</button> </button>
<button class="tbtn" id="bShot" title="截图时隐藏本窗(Agent 抓屏看不到);想看效果就关掉它">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 8.5h3l1.4-2h7.2L17 8.5h3v10H4z" />
<circle cx="12" cy="13.2" r="3.1" />
</svg>
</button>
<button class="tbtn" id="bSet" title="设置"> <button class="tbtn" id="bSet" title="设置">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3" /> <circle cx="12" cy="12" r="3.1" />
<path d="M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M18.4 5.6L17 7M7 17l-1.4 1.4" /> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
</svg> </svg>
</button> </button>
<button class="tbtn" id="bClose" title="关闭"> <button class="tbtn" id="bClose" title="关闭">
@@ -666,6 +672,7 @@
$('bPin').classList.toggle('on', S.posLock) $('bPin').classList.toggle('on', S.posLock)
$('bLock').classList.toggle('on', S.sizeLock) $('bLock').classList.toggle('on', S.sizeLock)
$('bTop').classList.toggle('on', S.topmost) $('bTop').classList.toggle('on', S.topmost)
$('bShot').classList.toggle('on', S.exclude)
$('sTop').classList.toggle('on', S.topmost) $('sTop').classList.toggle('on', S.topmost)
$('sPin').classList.toggle('on', S.posLock) $('sPin').classList.toggle('on', S.posLock)
$('sLock').classList.toggle('on', S.sizeLock) $('sLock').classList.toggle('on', S.sizeLock)
@@ -836,6 +843,7 @@
$('bFull').onclick = () => cmd('fullscreen') $('bFull').onclick = () => cmd('fullscreen')
$('bClose').onclick = () => cmd('close') $('bClose').onclick = () => cmd('close')
$('bSet').onclick = () => $('settings').classList.toggle('show') $('bSet').onclick = () => $('settings').classList.toggle('show')
$('bShot').onclick = () => cmd('exclude')
$('bSess').onclick = () => { const el = $('sessList'); renderSessions(); el.classList.toggle('show') } $('bSess').onclick = () => { const el = $('sessList'); renderSessions(); el.classList.toggle('show') }
$('sTop').onclick = () => cmd('topmost') $('sTop').onclick = () => cmd('topmost')
$('sPin').onclick = () => cmd('posLock') $('sPin').onclick = () => cmd('posLock')