diff --git a/static/db_admin.html b/static/db_admin.html index fdcea5f..a668576 100644 --- a/static/db_admin.html +++ b/static/db_admin.html @@ -296,6 +296,261 @@ font-size: 20px; } + .checkpoint-section.snapshot-section h3::before { + content: '🕘'; + } + + .snapshot-description { + font-size: 13px; + color: #555; + margin-bottom: 12px; + line-height: 1.6; + } + + .timeline-list { + display: flex; + flex-direction: column; + gap: 12px; + margin-top: 12px; + } + + .timeline-item { + display: flex; + gap: 14px; + background: white; + border: 1px solid #dde1ff; + border-radius: 10px; + padding: 14px 18px; + position: relative; + box-shadow: 0 4px 18px rgba(102, 126, 234, 0.08); + } + + .timeline-item-snapshot { + border-left: 4px solid #667eea; + } + + .timeline-item-checkpoint { + border-left: 4px solid #ff9800; + } + + .timeline-icon { + width: 40px; + height: 40px; + border-radius: 50%; + background: #eef2ff; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + flex-shrink: 0; + } + + .timeline-item-checkpoint .timeline-icon { + background: #fff4e5; + } + + .timeline-body { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; + } + + .timeline-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + } + + .timeline-title { + font-weight: 600; + color: #2f3e9e; + font-size: 15px; + } + + .timeline-item-checkpoint .timeline-title { + color: #e65100; + } + + .timeline-subtitle { + font-size: 14px; + color: #444; + font-weight: 500; + } + + .timeline-time { + font-size: 12px; + color: #888; + white-space: nowrap; + } + + .timeline-content { + font-size: 13px; + color: #333; + line-height: 1.6; + } + + .timeline-meta { + font-size: 12px; + color: #666; + display: flex; + flex-wrap: wrap; + gap: 10px; + } + + .timeline-note { + font-size: 12px; + color: #555; + background: #f7f9ff; + padding: 8px 10px; + border-radius: 6px; + } + + .timeline-stats { + font-size: 12px; + color: #333; + display: flex; + gap: 16px; + flex-wrap: wrap; + } + + .timeline-actions { + display: flex; + gap: 8px; + margin-top: 6px; + } + + .timeline-footer { + margin-top: 14px; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 10px; + } + + + .snapshot-filters { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 15px; + align-items: center; + } + + .snapshot-filters input, + .snapshot-filters select { + flex: 1 1 200px; + padding: 8px 10px; + border: 1px solid #d0d5ff; + border-radius: 6px; + font-size: 13px; + } + + .snapshot-filters select:disabled { + background: #f0f2ff; + color: #aaa; + } + + .snapshot-filters .filter-actions { + display: flex; + gap: 8px; + } + + .snapshot-table { + width: 100%; + border-collapse: collapse; + font-size: 13px; + } + + .snapshot-table th, + .snapshot-table td { + border-bottom: 1px solid #eceffb; + padding: 10px; + text-align: left; + vertical-align: top; + } + + .snapshot-table th { + background: #f4f6ff; + color: #334; + font-weight: 600; + } + + .snapshot-permit-name { + font-weight: 600; + color: #333; + } + + .snapshot-permit-region { + font-size: 12px; + color: #666; + margin-top: 4px; + } + + .snapshot-risk-text { + color: #333; + line-height: 1.5; + } + + .snapshot-risk-meta { + margin-top: 6px; + font-size: 12px; + color: #777; + } + + .snapshot-version-badge { + display: inline-flex; + align-items: center; + gap: 4px; + background: rgba(102, 126, 234, 0.12); + color: #4c51bf; + padding: 4px 8px; + border-radius: 12px; + font-size: 12px; + margin-bottom: 6px; + } + + .snapshot-status-tag { + display: inline-block; + font-size: 12px; + padding: 4px 8px; + border-radius: 12px; + background: #e8f5e9; + color: #2e7d32; + } + + .snapshot-editor { + font-weight: 600; + color: #333; + } + + .snapshot-note { + font-size: 12px; + color: #555; + margin-top: 6px; + } + + .snapshot-time { + font-size: 12px; + color: #888; + margin-top: 4px; + } + + .snapshot-footer { + margin-top: 12px; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 10px; + } + + .snapshot-pagination button { + min-width: 90px; + } + .checkpoint-form { margin-bottom: 20px; } @@ -866,8 +1121,29 @@ let historyStack = []; // 历史记录栈 let currentRegion = null; let currentTheme = null; - let currentPermit = null; - let pendingDangerOperation = null; // 待执行的危险操作 + let currentPermit = null; + let pendingDangerOperation = null; // 待执行的危险操作 + + const permitRiskSnapshotState = { + limit: 10, + offset: 0, + total: 0, + regionFilter: '', + permitFilter: '', + editorFilter: '', + snapshots: [], + loading: false, + error: '', + regionOptions: [], + regionLoading: false, + regionError: '', + permitOptions: [], + permitLoading: false, + permitOptionsError: '' + }; + let checkpointListCache = []; + let checkpointListLoading = false; + let checkpointListError = ''; // 步骤配置 const steps = { @@ -1266,23 +1542,36 @@ // 打开检查点模态窗口 async function openCheckpointModal() { const modal = document.getElementById('checkpointModal'); - const modalBody = document.getElementById('checkpointModalBody'); - modalBody.innerHTML = '
加载检查点列表...'; modal.classList.add('show'); - try { - // 添加时间戳参数避免缓存 - const response = await fetch(`/fs-ai-asistant/api/workflow/lawrisk/admin/checkpoints?t=${Date.now()}`); - const data = await response.json(); + // 重置并显示加载状态 + permitRiskSnapshotState.limit = 10; + permitRiskSnapshotState.offset = 0; + permitRiskSnapshotState.total = 0; + permitRiskSnapshotState.snapshots = []; + permitRiskSnapshotState.regionFilter = ''; + permitRiskSnapshotState.permitFilter = ''; + permitRiskSnapshotState.editorFilter = ''; + permitRiskSnapshotState.loading = true; + permitRiskSnapshotState.error = ''; + permitRiskSnapshotState.regionOptions = []; + permitRiskSnapshotState.permitOptions = []; + permitRiskSnapshotState.regionLoading = true; + permitRiskSnapshotState.regionError = ''; + permitRiskSnapshotState.permitLoading = false; + permitRiskSnapshotState.permitOptionsError = ''; - if (data.success) { - renderCheckpointManager(data.data.checkpoints); - } else { - modalBody.innerHTML = `暂无快照或检查点记录
'; + } else { + const snapshotStart = totalSnapshots ? snapshotState.offset + 1 : 0; + const snapshotEnd = totalSnapshots ? Math.min(snapshotState.offset + snapshotState.limit, totalSnapshots) : 0; + const disablePrev = snapshotState.offset === 0 ? 'disabled' : ''; + const disableNext = snapshotState.offset + snapshotState.limit >= totalSnapshots ? 'disabled' : ''; + + html += '暂无检查点
'; - } else { - html += '