fix: 审查修复波次(P0x4 + P1x30+)
- domain/rules: 计分与排名解耦、破纪录按组别、tieBreak 生效、调整分不丢、移除 aggregate 假能力 - realtime: 新建 internal/dto,快照三项契约对齐,/ws 只认会话身份 - httpapi: 流水幂等、standings 整表载荷、广播接线、强制改密、XFF 防伪造、records 写入、审计、赛事包内容、发布前备份、result.points、实例列表 - web: FormData 上传、YAML 解析、快照归一化、大屏解析层、bootstrap 降级、访客判定、主题切换 - console: 优雅关闭握手、中文化、免验证改管理员账号、选屏与日志轮转修复 - docs: 用户文档三份 + README - 主代理: 破纪录加分接线(levels 未加载导致恒 0)
This commit is contained in:
1 parent
8dae63ee70
commit
7f9701c465
61 files changed
+3844
-333
No files matched your search
@@ -21,6 +21,12 @@ const el = {
|
||||
btnRelayout: document.getElementById('btn-relayout'),
|
||||
btnOpenAdmin: document.getElementById('btn-open-admin'),
|
||||
btnClearLog: document.getElementById('btn-clear-log'),
|
||||
btnResetAccount: document.getElementById('btn-reset-account'),
|
||||
acctUser: document.getElementById('acct-user'),
|
||||
acctNewUser: document.getElementById('acct-new-user'),
|
||||
acctPassword: document.getElementById('acct-password'),
|
||||
acctStatus: document.getElementById('acct-status'),
|
||||
acctOutput: document.getElementById('acct-output'),
|
||||
titlebar: document.getElementById('titlebar'),
|
||||
winMin: document.getElementById('win-min'),
|
||||
winMax: document.getElementById('win-max'),
|
||||
@@ -137,6 +143,88 @@ function bindActions() {
|
||||
setLog([])
|
||||
})
|
||||
el.btnOpenAdmin.addEventListener('click', () => window.consoleApi.openServerAdmin())
|
||||
el.btnResetAccount.addEventListener('click', resetAccount)
|
||||
}
|
||||
|
||||
let accountStreaming = false
|
||||
|
||||
function setAccountOutput(text) {
|
||||
el.acctOutput.hidden = !text
|
||||
el.acctOutput.textContent = text || ''
|
||||
if (text) el.acctOutput.scrollTop = el.acctOutput.scrollHeight
|
||||
}
|
||||
|
||||
function appendAccountOutput(text) {
|
||||
el.acctOutput.hidden = false
|
||||
el.acctOutput.textContent += text
|
||||
el.acctOutput.scrollTop = el.acctOutput.scrollHeight
|
||||
}
|
||||
|
||||
function handleAccountOutput(text) {
|
||||
// 只在提交中接收流式输出:重置结束后的最终结果由返回值统一渲染,避免重复
|
||||
if (accountStreaming) appendAccountOutput(text)
|
||||
}
|
||||
|
||||
function setAccountStatus(text, kind) {
|
||||
el.acctStatus.hidden = !text
|
||||
el.acctStatus.textContent = text || ''
|
||||
el.acctStatus.className = kind ? `hint ${kind}` : 'hint'
|
||||
}
|
||||
|
||||
function setAccountBusy(busy) {
|
||||
el.btnResetAccount.disabled = busy
|
||||
el.btnResetAccount.textContent = busy ? '正在重置…' : '重置账号'
|
||||
for (const input of [el.acctUser, el.acctNewUser, el.acctPassword]) input.disabled = busy
|
||||
}
|
||||
|
||||
async function resetAccount() {
|
||||
const currentUsername = el.acctUser.value.trim()
|
||||
const newUsername = el.acctNewUser.value.trim()
|
||||
const password = el.acctPassword.value
|
||||
|
||||
if (!currentUsername) {
|
||||
setAccountStatus('请先填写当前用户名', 'err')
|
||||
return
|
||||
}
|
||||
|
||||
const target = newUsername ? `用户名改为「${newUsername}」` : '只重置密码'
|
||||
// 重置会踢掉该用户的所有登录态,属于不可撤销操作,必须先二次确认
|
||||
const confirmed = window.confirm(
|
||||
'确认重置管理员账号?\n\n' +
|
||||
`当前用户名:${currentUsername}\n` +
|
||||
`本次操作:${target}\n` +
|
||||
`新密码:${password ? '使用输入框中的密码' : '由程序随机生成'}\n\n` +
|
||||
'重置会作废该用户的全部登录会话,正在使用管理面板的人会被强制退出。'
|
||||
)
|
||||
if (!confirmed) return
|
||||
|
||||
accountStreaming = true
|
||||
setAccountBusy(true)
|
||||
setAccountOutput('')
|
||||
setAccountStatus('正在调用 scoreboard.exe passwd …')
|
||||
|
||||
try {
|
||||
const result = await window.consoleApi.resetAdminAccount({ currentUsername, newUsername, password })
|
||||
accountStreaming = false
|
||||
setAccountOutput(result.output || result.error || '')
|
||||
|
||||
if (result.ok) {
|
||||
setAccountStatus(
|
||||
password ? '重置成功,原会话已全部作废。' : '重置成功,密码为随机生成,请从下方输出抄录后立即修改。',
|
||||
'ok'
|
||||
)
|
||||
el.acctUser.value = newUsername || currentUsername
|
||||
el.acctNewUser.value = ''
|
||||
el.acctPassword.value = ''
|
||||
} else {
|
||||
setAccountStatus(`重置失败:${result.error || `passwd 退出码 ${result.exitCode}`}`, 'err')
|
||||
}
|
||||
} catch (err) {
|
||||
setAccountStatus(`重置失败:${err.message}`, 'err')
|
||||
} finally {
|
||||
accountStreaming = false
|
||||
setAccountBusy(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function boot() {
|
||||
@@ -144,6 +232,7 @@ async function boot() {
|
||||
bindWindowControls()
|
||||
window.consoleApi.onStatus(renderStatus)
|
||||
window.consoleApi.onLog(appendLog)
|
||||
window.consoleApi.onAccountOutput(handleAccountOutput)
|
||||
setLog(await window.consoleApi.getLog())
|
||||
await refresh()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user