接口加密
This commit is contained in:
@@ -65,6 +65,7 @@ func (s *Server) routes() {
|
||||
s.mux.HandleFunc("/api/log", s.handleAPILog)
|
||||
s.mux.HandleFunc("/api/runs", s.handleAPIRuns)
|
||||
s.mux.HandleFunc("/api/runs/record", s.handleAPIRecord)
|
||||
s.mux.HandleFunc("/api/runs/truncate", s.handleAPIRunsTruncate)
|
||||
s.mux.HandleFunc("/api/test/status", s.handleAPITestStatus)
|
||||
s.mux.HandleFunc("/api/test/sync", s.handleAPITestSync)
|
||||
|
||||
@@ -97,6 +98,7 @@ func (s *Server) handleAPIMeta(w http.ResponseWriter, r *http.Request) {
|
||||
"mysqlOk": s.deps.MySQLOK,
|
||||
"mysqlError": s.deps.MySQLErr,
|
||||
"allowTest": s.deps.AllowTest && s.deps.Runner != nil,
|
||||
"allowTruncate": s.deps.Store != nil && s.deps.MySQLOK,
|
||||
"hasRunner": s.deps.Runner != nil,
|
||||
"stepOptions": hy.StepSelectOptions(),
|
||||
"testStepOptions": hy.TestStepSelectOptions(),
|
||||
@@ -161,6 +163,31 @@ func (s *Server) handleAPIRecord(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, detail)
|
||||
}
|
||||
|
||||
func (s *Server) handleAPIRunsTruncate(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
writeErr(w, 405, "POST only")
|
||||
return
|
||||
}
|
||||
if s.deps.Store == nil || !s.deps.MySQLOK {
|
||||
writeErr(w, 503, "MySQL 未连接")
|
||||
return
|
||||
}
|
||||
if syncgate.IsRunning() {
|
||||
writeErr(w, 409, "已有同步任务在执行中")
|
||||
return
|
||||
}
|
||||
if err := s.deps.Store.TruncateAuditTables(); err != nil {
|
||||
applog.Appf("web truncate audit tables failed: %v", err)
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
applog.Appf("web truncate audit tables ok")
|
||||
writeJSON(w, map[string]any{
|
||||
"ok": true,
|
||||
"tables": []string{"hy_push_log", "hy_push_record", "hy_sync_job"},
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) handleAPITestStatus(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, enrichTestStatus(syncgate.GetStatus()))
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<select id="step"></select>
|
||||
</label>
|
||||
<button class="primary" id="load">刷新</button>
|
||||
<button type="button" class="danger" id="truncate" title="清空本机三表全部数据">清空三表</button>
|
||||
</div>
|
||||
<h3 style="color:var(--muted);font-size:0.95rem">同步任务</h3>
|
||||
<div style="overflow:auto;margin-bottom:1.5rem">
|
||||
@@ -37,11 +38,41 @@
|
||||
const anchorFromUrl = qs('anchor_date');
|
||||
if (anchorFromUrl) document.getElementById('anchor').value = anchorFromUrl;
|
||||
|
||||
const truncateBtn = document.getElementById('truncate');
|
||||
let pageMeta = null;
|
||||
|
||||
function updateTruncateButton(meta, syncRunning) {
|
||||
if (!truncateBtn) return;
|
||||
if (!meta || !meta.allowTruncate) {
|
||||
truncateBtn.disabled = true;
|
||||
truncateBtn.title = 'MySQL 未连接,无法清空';
|
||||
return;
|
||||
}
|
||||
if (syncRunning) {
|
||||
truncateBtn.disabled = true;
|
||||
truncateBtn.title = '同步任务执行中,请稍后再试';
|
||||
return;
|
||||
}
|
||||
truncateBtn.disabled = false;
|
||||
truncateBtn.title = '清空本机 hy_push_log / hy_push_record / hy_sync_job(不可恢复)';
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const m = await loadMeta();
|
||||
if (m && m.stepOptions) fillStepSelect(document.getElementById('step'), m.stepOptions);
|
||||
pageMeta = await loadMeta();
|
||||
if (pageMeta && pageMeta.stepOptions) fillStepSelect(document.getElementById('step'), pageMeta.stepOptions);
|
||||
updateTruncateButton(pageMeta, false);
|
||||
})();
|
||||
|
||||
async function refreshSyncGate() {
|
||||
try {
|
||||
const s = await api('/api/test/status');
|
||||
updateTruncateButton(pageMeta, !!(s && s.running));
|
||||
} catch (_) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
setInterval(refreshSyncGate, 2000);
|
||||
|
||||
async function load() {
|
||||
const anchor = document.getElementById('anchor').value;
|
||||
const step = document.getElementById('step').value;
|
||||
@@ -83,7 +114,26 @@ async function load() {
|
||||
}
|
||||
|
||||
document.getElementById('load').onclick = () => load().catch(e => alert(e.message));
|
||||
|
||||
truncateBtn.onclick = async () => {
|
||||
const tables = 'hy_push_log、hy_push_record、hy_sync_job';
|
||||
if (!confirm('将清空本机审计库三表(' + tables + '),不可恢复。\n仅影响本机 xk_hy_transit,不动云端数据。\n\n确定继续?')) return;
|
||||
const typed = prompt('请输入 TRUNCATE 以确认清空:');
|
||||
if (typed !== 'TRUNCATE') {
|
||||
if (typed !== null) alert('已取消:确认词不正确');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await api('/api/runs/truncate', { method: 'POST' });
|
||||
alert('三表已清空');
|
||||
await load();
|
||||
} catch (e) {
|
||||
alert(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
load().catch(e => alert(e.message));
|
||||
refreshSyncGate();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -66,6 +66,8 @@ button {
|
||||
background: #21262d;
|
||||
}
|
||||
button.primary { background: #238636; border-color: #2ea043; }
|
||||
button.danger { background: #da3633; border-color: var(--err); }
|
||||
button.danger:hover:not(:disabled) { filter: brightness(1.08); }
|
||||
button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
Reference in New Issue
Block a user