git-sync-web 自动提交 2026-09-09 18:02:17
This commit is contained in:
@@ -113,6 +113,17 @@ const Editor = {
|
||||
if (this.cm) this.cm.setOption('theme', dark ? 'material-darker' : 'eclipse');
|
||||
},
|
||||
refresh() { if (this.cm) setTimeout(() => this.cm.refresh(), 30); },
|
||||
setChangedLines(lines) {
|
||||
this._changed = lines && lines.length ? lines : null;
|
||||
if (!this.cm) return;
|
||||
const n = this.cm.lineCount();
|
||||
for (let i = 0; i < n; i++) this.cm.removeLineClass(i, 'background', 'cm-chg');
|
||||
if (!this._changed) return;
|
||||
for (const ln of this._changed) {
|
||||
const idx = ln - 1;
|
||||
if (idx >= 0 && idx < n) this.cm.addLineClass(idx, 'background', 'cm-chg');
|
||||
}
|
||||
},
|
||||
onSave: null, // 由 cm-boot.js 的快捷键触发
|
||||
onChange: null, // 由 cm-boot.js 的 change 事件触发(草稿缓存)
|
||||
};
|
||||
@@ -316,6 +327,8 @@ function openDetail(name) {
|
||||
$('#btn-delete').hidden = false;
|
||||
$('#btn-clone').hidden = false;
|
||||
fillForm(r);
|
||||
$('#summary-box').hidden = false;
|
||||
loadSummary(name);
|
||||
showTab('log');
|
||||
$('#modal').hidden = false;
|
||||
}
|
||||
@@ -328,10 +341,22 @@ function openCreate() {
|
||||
$('#btn-delete').hidden = true;
|
||||
$('#btn-clone').hidden = true;
|
||||
fillForm(null);
|
||||
$('#summary-box').hidden = true;
|
||||
showTab('config');
|
||||
$('#modal').hidden = false;
|
||||
}
|
||||
|
||||
async function loadSummary(name) {
|
||||
if (!name) return;
|
||||
try {
|
||||
const d = await api(`/api/repos/${name}/summary`);
|
||||
$('#f-summary').value = d.pending || '';
|
||||
$('#summary-log').textContent = d.log ? d.log.trim() : '(暂无本地变更摘要记录)';
|
||||
} catch (err) {
|
||||
$('#summary-log').textContent = '读取摘要失败:' + err.message;
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
$('#modal').hidden = true;
|
||||
current = null;
|
||||
@@ -817,6 +842,8 @@ async function loadFile(name, path) {
|
||||
showDraftNote(false);
|
||||
const d = await api(`/api/repos/${name}/file?path=${encodeURIComponent(path)}`);
|
||||
if (d.binary) {
|
||||
Editor.setChangedLines(null);
|
||||
const bh = $('#file-chg-hint'); if (bh) bh.hidden = true;
|
||||
Editor.value = `(二进制文件,大小 ${d.size} 字节,无法在网页编辑)`;
|
||||
Editor.disabled = true;
|
||||
draftServer = '';
|
||||
@@ -830,8 +857,13 @@ async function loadFile(name, path) {
|
||||
} else {
|
||||
Editor.value = draftServer;
|
||||
}
|
||||
Editor.setChangedLines(d.changed);
|
||||
const hint = $('#file-chg-hint');
|
||||
if (hint) hint.hidden = !(d.changed && d.changed.length);
|
||||
Editor.disabled = false;
|
||||
} catch (err) {
|
||||
Editor.setChangedLines(null);
|
||||
const eh = $('#file-chg-hint'); if (eh) eh.hidden = true;
|
||||
Editor.value = '读取失败:' + err.message;
|
||||
Editor.disabled = true;
|
||||
} finally {
|
||||
@@ -1069,6 +1101,19 @@ $('#btn-clone').addEventListener('click', () => {
|
||||
$('#f-name').focus();
|
||||
});
|
||||
|
||||
$('#btn-summary-save').addEventListener('click', async () => {
|
||||
if (!current) return;
|
||||
try {
|
||||
const res = await api(`/api/repos/${current}/summary`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ summary: $('#f-summary').value })
|
||||
});
|
||||
toast(res.ok ? '摘要已保存(本地,下次自动提交将使用此信息)' : '摘要保存失败', res.ok ? 'info' : 'error');
|
||||
await loadSummary(current);
|
||||
} catch (err) { toast('摘要保存失败:' + err.message, 'error'); }
|
||||
});
|
||||
|
||||
$('#btn-new').addEventListener('click', openCreate);
|
||||
$('#btn-empty-new').addEventListener('click', openCreate);
|
||||
$('#btn-sync-all').addEventListener('click', () => {
|
||||
|
||||
+14
-5
@@ -111,8 +111,9 @@
|
||||
</div>
|
||||
<div class="file-body" data-page-node-id="RXmkN5Ep4iegYWG3iWBiON">
|
||||
<div id="file-list" class="file-list" data-page-node-id="F75SFyDQShim9rZFPnjuJC">加载中…</div>
|
||||
<div class="file-edit-col" data-page-node-id="xh1qou2SVboDfvKTLcXFEA">
|
||||
<textarea id="file-editor" class="file-editor" placeholder="选择左侧文件进行编辑(Ctrl/Cmd + S 保存)" spellcheck="false"></textarea>
|
||||
<div class="file-edit-col" data-page-node-id="xh1qou2SVboDfvKTLcXFEA">
|
||||
<div class="file-chg-hint" id="file-chg-hint" hidden>● 黄色高亮 = 相对最近一次提交仍未提交的修改行</div>
|
||||
<textarea id="file-editor" class="file-editor" placeholder="选择左侧文件进行编辑(Ctrl/Cmd + S 保存)" spellcheck="false"></textarea>
|
||||
<div class="file-actions" data-page-node-id="GAMAnkYKeMi93EVEx8eYOn">
|
||||
<input id="file-msg" class="file-msg" placeholder="提交说明(可选)" data-page-node-id="aS2jRAr1kAkqElk1T4Cldz">
|
||||
<button class="btn btn-sm" id="btn-file-save" data-page-node-id="gaVGyD6YkFFElkXJFBtLk5">保存</button>
|
||||
@@ -205,10 +206,18 @@
|
||||
<input name="cron" id="f-cron" placeholder="*/30 * * * * 表示每 30 分钟,留空使用固定间隔" data-page-node-id="6W3Ua8pPoGLuaNh7rGcDOw">
|
||||
<span id="cron-next" class="cron-next" data-page-node-id="WgXuBnZPqGWvOBGRxzIVCn"></span>
|
||||
</label>
|
||||
<label class="full" data-page-node-id="fsjZ6wLid5NUBV0yAHKdII">日志文件路径(留空使用默认 logs/配置名.log)
|
||||
<input name="log_file" id="f-log" data-page-node-id="KJpv7jEWYnOQZ1PtQMetfP">
|
||||
</label>
|
||||
<label class="full" data-page-node-id="fsjZ6wLid5NUBV0yAHKdII">日志文件路径(留空使用默认 logs/配置名.log)
|
||||
<input name="log_file" id="f-log" data-page-node-id="KJpv7jEWYnOQZ1PtQMetfP">
|
||||
</label>
|
||||
<div class="summary-box" id="summary-box" hidden>
|
||||
<div class="summary-head">
|
||||
<span>变更摘要(本地,不同步)</span>
|
||||
<button type="button" class="btn btn-sm" id="btn-summary-save">保存摘要</button>
|
||||
</div>
|
||||
<textarea id="f-summary" class="file-editor" style="min-height:84px" placeholder="填写后将作为【自动提交】的下一次 commit 信息;留空则由工具自动生成一句话并在本地记录。此摘要与映射仅存于本地 summaries/,不会上传。"></textarea>
|
||||
<div class="summary-log" id="summary-log"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions" data-page-node-id="1GfIJLKdxSyPwBqpqCCMb9">
|
||||
<button type="submit" class="btn btn-primary" data-page-node-id="E2123htNE6lmoNzZTg7AwV">保存</button>
|
||||
<button type="button" class="btn" id="btn-clone" hidden data-page-node-id="H6BdDiraff2cjD9EWjF8Eh">克隆此配置</button>
|
||||
|
||||
@@ -145,11 +145,19 @@ textarea { font-family: Consolas, monospace; resize: vertical; }
|
||||
.file-item { padding: 4px 8px; border-radius: 6px; font-size: 12.5px; font-family: Consolas, monospace; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.file-item:hover { background: #f0f3f6; }
|
||||
.file-edit-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
|
||||
.file-chg-hint { font-size: 12px; color: #9a6b00; background: rgba(255, 196, 0, 0.12); border: 1px solid rgba(224, 160, 32, 0.4); border-radius: 6px; padding: 4px 8px; }
|
||||
html.dark .file-chg-hint { color: #d9a93a; background: rgba(255, 196, 0, 0.1); border-color: rgba(201, 143, 28, 0.4); }
|
||||
.file-editor { flex: 1; min-height: 360px; width: 100%; border: 1px solid var(--border); border-radius: 8px; padding: 10px; font: 12.5px/1.55 Consolas, monospace; color: var(--text); background: #fff; white-space: pre; overflow: auto; }
|
||||
.file-editor:disabled { background: #f6f7f9; color: var(--muted); }
|
||||
.file-actions { display: flex; gap: 8px; align-items: center; }
|
||||
.file-msg { flex: 1; }
|
||||
|
||||
.summary-box { margin-top: 16px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); }
|
||||
.summary-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-size: 13px; color: var(--muted); }
|
||||
.summary-head .btn-sm { padding: 4px 10px; font-size: 12px; }
|
||||
.summary-log { margin-top: 10px; padding: 10px 12px; border: 1px dashed var(--border); border-radius: 8px; background: #fafbfc; font: 12px/1.6 Consolas, "Microsoft YaHei", monospace; color: var(--text); white-space: pre-wrap; max-height: 220px; overflow: auto; }
|
||||
html.dark .summary-log { background: #12151a; }
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.file-body { flex-direction: column; }
|
||||
.file-list { width: 100%; max-height: 200px; }
|
||||
@@ -241,6 +249,16 @@ html.dark .file-editor { background: #12151a; }
|
||||
.CodeMirror { height: 420px; border: 1px solid var(--border); border-radius: 8px; font: 12.5px/1.55 Consolas, monospace; }
|
||||
.CodeMirror-scroll { min-height: 380px; }
|
||||
|
||||
/* 未提交修改行高亮 */
|
||||
.CodeMirror-linebackground.cm-chg {
|
||||
background-color: rgba(255, 196, 0, 0.16);
|
||||
box-shadow: inset 3px 0 0 0 #e0a020;
|
||||
}
|
||||
html.dark .CodeMirror-linebackground.cm-chg {
|
||||
background-color: rgba(255, 196, 0, 0.13);
|
||||
box-shadow: inset 3px 0 0 0 #c98f1c;
|
||||
}
|
||||
|
||||
/* ---------- 冲突文件内联编辑 ---------- */
|
||||
.cf-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
|
||||
.cf-head h4 { margin: 0; flex: 1; }
|
||||
|
||||
Reference in New Issue
Block a user