feat(server): 新增修改密码接口 POST /api/auth/password(验原密码、作废会话)
This commit is contained in:
1 parent
ad2322d558
commit
4cbf5a74f0
13 files changed
+528
-20
No files matched your search
+108
-4
@@ -30,6 +30,7 @@ function main() {
|
||||
let service = null
|
||||
let displays = null
|
||||
let adminWindow = null
|
||||
let serverAdminWindow = null
|
||||
let tray = null
|
||||
let powerBlockerId = null
|
||||
let displayFallbackTimer = null
|
||||
@@ -90,6 +91,9 @@ function main() {
|
||||
title: 'Scoreboard Console · 启动管理',
|
||||
backgroundColor: '#0f1420',
|
||||
show: false,
|
||||
// 标题栏由页面自绘;titleBarStyle 只是兜底,防止某些平台忽略 frame:false
|
||||
frame: false,
|
||||
titleBarStyle: 'hidden',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, '..', 'renderer', 'preload.js'),
|
||||
contextIsolation: true,
|
||||
@@ -98,6 +102,7 @@ function main() {
|
||||
}
|
||||
})
|
||||
|
||||
bindWindowStateEvents(adminWindow)
|
||||
adminWindow.loadFile(path.join(__dirname, '..', 'renderer', 'index.html'))
|
||||
adminWindow.once('ready-to-show', () => adminWindow.show())
|
||||
|
||||
@@ -114,6 +119,79 @@ function main() {
|
||||
})
|
||||
}
|
||||
|
||||
function adminPanelUrl() {
|
||||
// 复用服务端的地址推导:host 配成 0.0.0.0 时本机也要走回环
|
||||
if (service) return service.status.adminUrl
|
||||
const host = (cfg.values.server.host || '127.0.0.1') === '0.0.0.0' ? '127.0.0.1' : cfg.values.server.host
|
||||
return `http://${host || '127.0.0.1'}:${cfg.values.server.port}/admin`
|
||||
}
|
||||
|
||||
function showServerAdmin() {
|
||||
if (!serverAdminWindow || serverAdminWindow.isDestroyed()) {
|
||||
createServerAdminWindow()
|
||||
return
|
||||
}
|
||||
if (serverAdminWindow.isMinimized()) serverAdminWindow.restore()
|
||||
serverAdminWindow.show()
|
||||
serverAdminWindow.focus()
|
||||
}
|
||||
|
||||
// 服务端管理面板是 Web 页面,用无边框 Electron 窗口承载,省得现场再开浏览器
|
||||
function createServerAdminWindow() {
|
||||
const { width, height } = cfg.values.admin
|
||||
serverAdminWindow = new BrowserWindow({
|
||||
width: Math.max(width, 1100),
|
||||
height,
|
||||
minWidth: 900,
|
||||
minHeight: 620,
|
||||
title: 'Scoreboard · 服务端管理面板',
|
||||
backgroundColor: '#161616',
|
||||
show: false,
|
||||
frame: false,
|
||||
titleBarStyle: 'hidden',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, '..', 'renderer', 'shell-preload.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: true
|
||||
}
|
||||
})
|
||||
|
||||
bindWindowStateEvents(serverAdminWindow)
|
||||
|
||||
const url = adminPanelUrl()
|
||||
log.push('console', `打开服务端管理面板:${url}`)
|
||||
serverAdminWindow.loadURL(url).catch((err) => {
|
||||
log.push('console', `服务端管理面板加载失败:${err.message}`)
|
||||
})
|
||||
|
||||
// 加载失败时 ready-to-show 不会触发,兜底把窗口显示出来,否则用户看不到任何反馈
|
||||
const reveal = () => {
|
||||
if (serverAdminWindow && !serverAdminWindow.isDestroyed()) {
|
||||
serverAdminWindow.show()
|
||||
serverAdminWindow.focus()
|
||||
}
|
||||
}
|
||||
serverAdminWindow.once('ready-to-show', reveal)
|
||||
serverAdminWindow.webContents.on('did-fail-load', (_event, _code, _desc, _url, isMainFrame) => {
|
||||
if (isMainFrame) reveal()
|
||||
})
|
||||
|
||||
serverAdminWindow.on('closed', () => {
|
||||
serverAdminWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// 渲染层要随时知道最大化状态,才能在「最大化/还原」之间换图标
|
||||
function bindWindowStateEvents(win) {
|
||||
const notify = () => {
|
||||
if (win.isDestroyed()) return
|
||||
win.webContents.send('window:maximize-changed', win.isMaximized())
|
||||
}
|
||||
win.on('maximize', notify)
|
||||
win.on('unmaximize', notify)
|
||||
}
|
||||
|
||||
function ensureDisplays() {
|
||||
if (displaysEnabled || !displays) return
|
||||
displaysEnabled = true
|
||||
@@ -138,10 +216,7 @@ function main() {
|
||||
{ label: '重启服务', enabled: busy, click: () => service.restart() },
|
||||
{ type: 'separator' },
|
||||
{ label: '打开管理端', click: () => showAdmin() },
|
||||
{
|
||||
label: '打开服务端管理面板',
|
||||
click: () => shell.openExternal(status.adminUrl || `http://127.0.0.1:${cfg.values.server.port}/admin`)
|
||||
},
|
||||
{ label: '打开服务端管理面板', click: () => showServerAdmin() },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '退出',
|
||||
@@ -202,6 +277,35 @@ function main() {
|
||||
showAdmin()
|
||||
return true
|
||||
})
|
||||
ipcMain.handle('app:open-server-admin', () => {
|
||||
showServerAdmin()
|
||||
return true
|
||||
})
|
||||
|
||||
// 窗口控制统一从 event.sender 反查窗口,多个窗口共用同一套通道
|
||||
ipcMain.handle('window:minimize', (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
if (win && !win.isDestroyed()) win.minimize()
|
||||
return true
|
||||
})
|
||||
ipcMain.handle('window:maximize', (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
if (!win || win.isDestroyed()) return false
|
||||
// 以「切换」语义实现,避免按钮在已最大化时点了没反应
|
||||
const next = !win.isMaximized()
|
||||
if (next) win.maximize()
|
||||
else win.unmaximize()
|
||||
return next
|
||||
})
|
||||
ipcMain.handle('window:close', (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
if (win && !win.isDestroyed()) win.close()
|
||||
return true
|
||||
})
|
||||
ipcMain.handle('window:is-maximized', (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender)
|
||||
return Boolean(win && !win.isDestroyed() && win.isMaximized())
|
||||
})
|
||||
}
|
||||
|
||||
app.on('second-instance', () => showAdmin())
|
||||
|
||||
Reference in new issue
Block a user