feat(console): 开机自启默认关闭,服务管理窗口加手动开关
- DEFAULTS.startup.openAtLogin 与随包 config.json 默认改为 false;
applyOpenAtLogin 只有显式 true 才注册登录项(缺省/null/false 都不注册)
- config.js 新增 updateConfig():只写回文件里已有的键 + 目标键,不把 DEFAULTS 落盘
- 主进程 setOpenAtLogin():改内存 → 写回 config.json → setLoginItemSettings,
任一失败都回滚,返回 {ok, openAtLogin};状态快照新增 openAtLogin / openAtLoginSupported
- 渲染层:服务端状态卡片新增「开机自启」滑块(纯 CSS,无依赖),
切换即时生效并有本地意图守卫,避免被随后到达的陈旧快照冲掉
- 文档:console/README.md 与 docs/部署指南.md 同步
注意:旧包 config.json 里已显式写 true 的用户升级后仍会自启(不悄悄改既有行为),
在窗口里关一次即可;全新安装默认不注册。
This commit is contained in:
1 parent
7c59dba9b9
commit
1b78c38bb8
9 files changed
+204
-12
No files matched your search
@@ -9,6 +9,8 @@ const el = {
|
||||
pid: document.getElementById('k-pid'),
|
||||
restarts: document.getElementById('k-restarts'),
|
||||
power: document.getElementById('k-power'),
|
||||
openAtLogin: document.getElementById('sw-open-at-login'),
|
||||
openAtLoginLabel: document.getElementById('sw-open-at-login-label'),
|
||||
exe: document.getElementById('k-exe'),
|
||||
config: document.getElementById('k-config'),
|
||||
configWarning: document.getElementById('config-warning'),
|
||||
@@ -56,6 +58,7 @@ function renderStatus(status) {
|
||||
el.pid.textContent = status.pid || '—'
|
||||
el.restarts.textContent = status.restarts ? `${status.restarts} 次` : '0 次'
|
||||
el.power.textContent = status.powerSaveBlocked ? '已启用(阻止显示器休眠)' : '未启用'
|
||||
renderOpenAtLogin(status)
|
||||
el.exe.textContent = status.exePath || '—'
|
||||
el.config.textContent = status.configPath || '—'
|
||||
|
||||
@@ -74,6 +77,66 @@ function renderStatus(status) {
|
||||
renderDisplays(status.displays || [])
|
||||
}
|
||||
|
||||
// 切换后状态快照可能还停在旧值(轮询与写配置存在时间差),用它兜底:
|
||||
// 等快照追上新值再交还轮询,避免刚点下的开关被旧快照冲回去。
|
||||
let openAtLoginPending = null
|
||||
let openAtLoginPendingTimer = null
|
||||
|
||||
function setOpenAtLoginPending(value) {
|
||||
openAtLoginPending = value
|
||||
if (openAtLoginPendingTimer) clearTimeout(openAtLoginPendingTimer)
|
||||
openAtLoginPendingTimer = null
|
||||
if (value === null) return
|
||||
openAtLoginPendingTimer = setTimeout(() => {
|
||||
openAtLoginPending = null
|
||||
openAtLoginPendingTimer = null
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
function renderOpenAtLogin(status) {
|
||||
const supported = status.openAtLoginSupported === true
|
||||
let enabled = status.openAtLogin === true
|
||||
if (openAtLoginPending !== null) {
|
||||
if (enabled === openAtLoginPending) setOpenAtLoginPending(null)
|
||||
else enabled = openAtLoginPending
|
||||
}
|
||||
el.openAtLogin.checked = enabled
|
||||
el.openAtLogin.disabled = !supported
|
||||
el.openAtLogin.title = supported ? '' : '仅打包后的 Windows 版本生效'
|
||||
el.openAtLoginLabel.textContent = enabled ? '已开启' : '已关闭'
|
||||
}
|
||||
|
||||
async function toggleOpenAtLogin() {
|
||||
const wanted = el.openAtLogin.checked
|
||||
// 写配置期间锁住开关,避免连点触发多次写入
|
||||
el.openAtLogin.disabled = true
|
||||
setOpenAtLoginPending(wanted)
|
||||
el.openAtLoginLabel.textContent = wanted ? '已开启' : '已关闭'
|
||||
|
||||
let result
|
||||
try {
|
||||
result = await window.consoleApi.setOpenAtLogin(wanted)
|
||||
} catch (err) {
|
||||
result = { ok: false, message: err.message }
|
||||
}
|
||||
|
||||
if (result && result.ok) {
|
||||
// 用返回值即时更新,不必等下一次状态快照
|
||||
const applied = result.openAtLogin === true
|
||||
setOpenAtLoginPending(applied)
|
||||
el.openAtLogin.checked = applied
|
||||
el.openAtLoginLabel.textContent = applied ? '已开启' : '已关闭'
|
||||
} else {
|
||||
// 失败:回滚勾选;原因由主进程写进运行日志,这里再给个 title 提示
|
||||
setOpenAtLoginPending(null)
|
||||
el.openAtLogin.checked = !wanted
|
||||
el.openAtLoginLabel.textContent = !wanted ? '已开启' : '已关闭'
|
||||
el.openAtLogin.title = (result && result.message) || '设置开机自启失败'
|
||||
}
|
||||
|
||||
el.openAtLogin.disabled = false
|
||||
}
|
||||
|
||||
function renderDisplays(displays) {
|
||||
el.displayList.textContent = ''
|
||||
if (!displays.length) {
|
||||
@@ -185,6 +248,7 @@ function bindActions() {
|
||||
})
|
||||
el.btnOpenAdmin.addEventListener('click', () => window.consoleApi.openServerAdmin())
|
||||
el.btnResetAccount.addEventListener('click', resetAccount)
|
||||
el.openAtLogin.addEventListener('change', toggleOpenAtLogin)
|
||||
}
|
||||
|
||||
let accountStreaming = false
|
||||
|
||||
Reference in new issue
Block a user