git-sync-web 自动提交 2026-09-09 10:33:29

This commit is contained in:
tamakyi
2026-09-09 10:33:29 +08:00
parent 1bf1f72901
commit 7c9be4b44b
3 changed files with 92 additions and 8 deletions
+47
View File
@@ -64,6 +64,7 @@ function card(r) {
${r.conflicts && r.conflicts.length ? `<span class="badge b-conflict">冲突 ${r.conflicts.length}</span>` : ''}
</div>
<div class="last">上次同步:${esc(last)}</div>
${r.last_sync && r.last_sync.detail ? `<div class="last-detail" title="${esc(r.last_sync.detail)}">${esc(r.last_sync.detail)}</div>` : ''}
${r.status === 'error' && r.last_error ? `<div class="err" title="${esc(r.last_error)}">${esc(r.last_error)}</div>` : ''}
<div class="card-btns">
<button class="btn" data-act="sync" ${r.running ? '' : 'disabled'}>立即同步</button>
@@ -106,6 +107,7 @@ function connect() {
if (i >= 0) repos[i] = msg.data; else repos.push(msg.data);
render();
} else if (msg.type === 'log') {
appendLiveLine(msg);
if (current === msg.repo && !$('#tab-log').hidden) appendLogLine(`[${msg.time}] ${msg.msg}`);
}
};
@@ -115,8 +117,52 @@ function setConn(ok) {
const el = $('#conn');
el.textContent = ok ? '● 已连接' : '● 未连接';
el.className = 'conn ' + (ok ? 'on' : 'off');
const live = $('#live-conn');
if (live) {
live.textContent = ok ? '● 已连接' : '● 未连接';
live.className = 'conn ' + (ok ? 'on' : 'off');
}
}
// ---------- 全局实时活动面板 ----------
const LIVE_MAX = 400;
function appendLiveLine(msg) {
const box = $('#live-log');
if (!box) return;
let level = 'info';
if (msg.level === 'error') level = 'err';
else if (msg.level === 'warn') level = 'warn';
const line = document.createElement('div');
line.className = 'live-line lv-' + level;
line.innerHTML = `<span class="ll-time">${esc(msg.time)}</span><span class="ll-repo">${esc(msg.repo)}</span><span class="ll-msg">${esc(msg.msg)}</span>`;
box.appendChild(line);
while (box.childElementCount > LIVE_MAX) box.removeChild(box.firstChild);
box.scrollTop = box.scrollHeight;
}
function clearLive() {
const box = $('#live-log');
if (box) box.innerHTML = '';
}
// 载入各仓库最近日志作为初始上下文,避免面板一开始空白
async function seedLive() {
const names = repos.map(r => r.name);
await Promise.all(names.map(async (name) => {
try {
const d = await api(`/api/repos/${name}/log?lines=8`);
if (d.lines && d.lines.length) {
d.lines.forEach(t => {
const m = t.match(/^\[(.+?)\] (.*)$/);
appendLiveLine({ time: m ? m[1] : '', repo: name, msg: m ? m[2] : t, level: 'info', seed: true });
});
}
} catch (_) { /* 忽略 */ }
}));
}
$('#btn-live-clear').addEventListener('click', clearLive);
// ---------- 登录 ----------
function showLogin() {
const el = $('#login');
@@ -411,6 +457,7 @@ async function refresh() {
const d = await api('/api/status');
repos = d.repos || [];
render();
seedLive();
} catch (e) { /* 忽略,SSE 会重试 */ }
}