- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次) - .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…), 目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪 - .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/) - .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*) - .gitignore 补:备份件(*.bak-*) - 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
50 lines
2.7 KiB
Python
50 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
||
import io
|
||
p = '/opt/dshs/web/admin.html'
|
||
s = io.open(p, encoding='utf-8').read()
|
||
anchor = """ <table class="admin">
|
||
<thead><tr><th>用户名</th><th>角色</th><th>注册时间</th><th>操作</th></tr></thead>
|
||
<tbody id="users"></tbody>
|
||
</table>
|
||
"""
|
||
assert anchor in s
|
||
block = anchor + """
|
||
<h3 style="margin:22px 0 8px">存储用量 <span class="auth-sub" id="storageAt" style="font-weight:400"></span></h3>
|
||
<table class="admin">
|
||
<thead><tr><th>用户</th><th>工作区</th><th>会话</th><th>回收站</th><th>可清理</th></tr></thead>
|
||
<tbody id="storage"></tbody>
|
||
</table>
|
||
<p class="auth-sub" style="margin:6px 0 0">工作区达 <span id="thWs"></span> / 会话达 <span id="thSess"></span> 时由每日维护任务自动清理(工作区 90 天、会话 365 天前的记录;均先入回收站保留 30 天)。</p>
|
||
"""
|
||
s = s.replace(anchor, block, 1)
|
||
js_anchor = " document.getElementById('logoutBtn').addEventListener('click', async () => {"
|
||
assert js_anchor in s
|
||
js = """ function fmtB(b) { return b >= 1073741824 ? (b / 1073741824).toFixed(2) + ' GB' : (b / 1048576).toFixed(1) + ' MB' }
|
||
async function loadStorage() {
|
||
const tbody = document.getElementById('storage')
|
||
try {
|
||
const r = await (await fetch('/api/admin/storage')).json()
|
||
document.getElementById('storageAt').textContent = r.generatedAt ? `(更新于 ${new Date(r.generatedAt).toLocaleString()})` : ''
|
||
if (r.thresholds) {
|
||
document.getElementById('thWs').textContent = r.thresholds.wsMB + ' MB'
|
||
document.getElementById('thSess').textContent = r.thresholds.sessionsMB + ' MB'
|
||
}
|
||
tbody.innerHTML = (r.users ?? []).map((u) => `<tr>
|
||
<td>${esc(u.username)}</td>
|
||
<td style="${u.wsOver ? 'color:var(--danger)' : ''}">${fmtB(u.ws)}</td>
|
||
<td style="${u.sessionsOver ? 'color:var(--danger)' : ''}">${fmtB(u.sessions)}</td>
|
||
<td>${fmtB(u.trash)}</td>
|
||
<td>${u.cleanableT1 + u.cleanableT2} 项 / ${fmtB(u.cleanableBytes)}</td>
|
||
</tr>`).join('') || `<tr><td colspan="5" class="auth-sub">${esc(r.note ?? '暂无数据')}</td></tr>`
|
||
} catch { tbody.innerHTML = '<tr><td colspan="5" class="auth-sub">读取失败</td></tr>' }
|
||
}
|
||
""" + js_anchor
|
||
s = s.replace(js_anchor, js, 1)
|
||
call_anchor = " await loadUsers()"
|
||
if call_anchor in s:
|
||
s = s.replace(call_anchor, call_anchor + "\n await loadStorage()", 1)
|
||
else:
|
||
s = s.replace("loadUsers()", "loadUsers(); loadStorage()", 1)
|
||
io.open(p, 'w', encoding='utf-8', newline='').write(s)
|
||
print('E admin.html 用量区块已写入')
|