git-sync-web 自动提交 2026-09-09 12:38:18
This commit is contained in:
+114
@@ -108,6 +108,7 @@ function connect() {
|
||||
if (i >= 0) repos[i] = msg.data; else repos.push(msg.data);
|
||||
render();
|
||||
updateConflictActions();
|
||||
if (current === msg.repo && !$('#tab-diff').hidden) loadDiff(msg.repo);
|
||||
} else if (msg.type === 'log') {
|
||||
appendLiveLine(msg);
|
||||
if (current === msg.repo && !$('#tab-log').hidden) appendLogLine(`[${msg.time}] ${msg.msg}`);
|
||||
@@ -206,6 +207,8 @@ function showTab(t) {
|
||||
document.querySelectorAll('.tab-pane').forEach(p => { p.hidden = p.id !== 'tab-' + t; });
|
||||
if (t === 'log' && current) loadLog(current);
|
||||
if (t === 'history' && current) loadHistory(current);
|
||||
if (t === 'diff' && current) loadDiff(current);
|
||||
if (t === 'file' && current) loadTree(current);
|
||||
if (t === 'conflict' && current) { loadConflicts(current); updateConflictActions(); }
|
||||
if (t === 'stats' && current) loadStats(current);
|
||||
}
|
||||
@@ -367,6 +370,117 @@ function updateConflictActions() {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 差异显示(网页端) ----------
|
||||
function loadDiff(name) {
|
||||
const scope = $('#f-diff-scope').value;
|
||||
const box = $('#diffbox');
|
||||
const stat = $('#diff-stat');
|
||||
box.textContent = '加载中…';
|
||||
stat.innerHTML = '';
|
||||
api(`/api/repos/${name}/diff?scope=${encodeURIComponent(scope)}`).then(d => {
|
||||
renderDiff(box, d.text || '(无差异)');
|
||||
if (d.files && d.files.length) {
|
||||
stat.innerHTML = d.files.map(f =>
|
||||
`<span class="df ${f.add ? 'df-add' : ''} ${f.del ? 'df-del' : ''}">${esc(f.path)} <b style="color:var(--green)">+${f.add}</b> <b style="color:var(--red)">-${f.del}</b></span>`
|
||||
).join('');
|
||||
} else if (d.stat) {
|
||||
stat.textContent = d.stat.trim();
|
||||
}
|
||||
}).catch(err => { box.textContent = '差异加载失败:' + err.message; });
|
||||
}
|
||||
|
||||
function renderDiff(box, text) {
|
||||
box.innerHTML = '';
|
||||
const lines = String(text).split('\n');
|
||||
const frag = document.createDocumentFragment();
|
||||
lines.forEach(line => {
|
||||
const pre = document.createElement('div');
|
||||
pre.className = 'diff-line';
|
||||
if (line.startsWith('+')) pre.classList.add('diff-add');
|
||||
else if (line.startsWith('-')) pre.classList.add('diff-del');
|
||||
else if (line.startsWith('@@')) pre.classList.add('diff-hunk');
|
||||
pre.textContent = line === '' ? ' ' : line;
|
||||
frag.appendChild(pre);
|
||||
});
|
||||
box.appendChild(frag);
|
||||
}
|
||||
|
||||
// ---------- 文件编辑(网页端) ----------
|
||||
let fileCurrent = null;
|
||||
function loadTree(name) {
|
||||
const list = $('#file-list');
|
||||
list.textContent = '加载中…';
|
||||
api(`/api/repos/${name}/tree`).then(d => {
|
||||
const files = d.files || [];
|
||||
if (!files.length) { list.textContent = '(无文件)'; return; }
|
||||
list.innerHTML = files.map(f =>
|
||||
`<div class="file-item" data-path="${esc(f.path)}" title="${esc(f.path)}">${esc(f.path)}</div>`
|
||||
).join('');
|
||||
}).catch(err => { list.textContent = '文件列表加载失败:' + err.message; });
|
||||
}
|
||||
|
||||
async function loadFile(name, path) {
|
||||
const editor = $('#file-editor');
|
||||
editor.value = '加载中…';
|
||||
editor.disabled = false;
|
||||
$('#file-current').textContent = path;
|
||||
fileCurrent = path;
|
||||
try {
|
||||
const d = await api(`/api/repos/${name}/file?path=${encodeURIComponent(path)}`);
|
||||
if (d.binary) {
|
||||
editor.value = `(二进制文件,大小 ${d.size} 字节,无法在网页编辑)`;
|
||||
editor.disabled = true;
|
||||
} else {
|
||||
editor.value = d.content || '';
|
||||
editor.disabled = false;
|
||||
}
|
||||
} catch (err) {
|
||||
editor.value = '读取失败:' + err.message;
|
||||
editor.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
async function saveFile(commit) {
|
||||
const name = current;
|
||||
const path = fileCurrent;
|
||||
if (!name || !path) { alert('请先在左侧选择一个文件'); return; }
|
||||
const editor = $('#file-editor');
|
||||
if (editor.disabled) { alert('当前文件不可编辑(二进制或读取失败)'); return; }
|
||||
const content = editor.value;
|
||||
try {
|
||||
// 先写盘
|
||||
await api(`/api/repos/${name}/file`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ path, content })
|
||||
});
|
||||
if (commit) {
|
||||
await api(`/api/repos/${name}/commit`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ path, message: $('#file-msg').value })
|
||||
});
|
||||
alert('已保存并提交');
|
||||
} else {
|
||||
// 保存后自动切到差异预览
|
||||
$('#f-diff-scope').value = 'working';
|
||||
showTab('diff');
|
||||
alert('已保存到磁盘(未提交)。可在「差异」tab 查看改动,或稍后由自动同步提交。');
|
||||
}
|
||||
} catch (err) { alert('保存失败:' + err.message); }
|
||||
}
|
||||
|
||||
$('#f-diff-scope').addEventListener('change', () => { if (current && !$('#tab-diff').hidden) loadDiff(current); });
|
||||
$('#btn-diff-refresh').addEventListener('click', () => { if (current) loadDiff(current); });
|
||||
$('#btn-file-refresh').addEventListener('click', () => { if (current) loadTree(current); });
|
||||
$('#file-list').addEventListener('click', (e) => {
|
||||
const item = e.target.closest('.file-item');
|
||||
if (!item || !current) return;
|
||||
loadFile(current, item.dataset.path);
|
||||
});
|
||||
$('#btn-file-save').addEventListener('click', () => saveFile(false));
|
||||
$('#btn-file-commit').addEventListener('click', () => saveFile(true));
|
||||
|
||||
// ---------- 统计 ----------
|
||||
function dateStr(d) {
|
||||
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
|
||||
|
||||
Reference in New Issue
Block a user