回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复: - 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录) - tmp/(32.4 M,按接续棒命名的过程临时区) - .workbuddy/tmp/(39.5 M) - 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物) - tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留 入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与 接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、 .workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。 排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、 打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
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 用量区块已写入')
|