Update: Js 4 Log.html 80%

This commit is contained in:
XOF
2025-11-26 20:36:25 +08:00
parent 01c9b34600
commit c86e7a7ba4
17 changed files with 1120 additions and 473 deletions

View File

@@ -1,4 +1,3 @@
// Filename: frontend/js/pages/logs/index.js
import { apiFetchJson } from '../../services/api.js';
import LogList from './logList.js';
import CustomSelectV2 from '../../components/customSelectV2.js';
@@ -8,11 +7,13 @@ import { STATIC_ERROR_MAP, STATUS_CODE_MAP } from './logList.js';
import SystemLogTerminal from './systemLog.js';
import { initBatchActions } from './batchActions.js';
import flatpickr from '../../vendor/flatpickr.js';
import LogSettingsModal from './logSettingsModal.js';
const dataStore = {
groups: new Map(),
keys: new Map(),
};
class LogsPage {
constructor() {
this.state = {
@@ -40,6 +41,7 @@ class LogsPage {
systemControls: document.getElementById('system-logs-controls'),
errorTemplate: document.getElementById('error-logs-template'),
systemTemplate: document.getElementById('system-logs-template'),
settingsBtn: document.querySelector('button[aria-label="日志设置"]'),
};
this.initialized = !!this.elements.contentContainer;
if (this.initialized) {
@@ -48,15 +50,87 @@ class LogsPage {
this.debouncedLoadAndRender = debounce(() => this.loadAndRenderLogs(), 300);
this.fp = null;
this.themeObserver = null;
this.settingsModal = null;
this.currentSettings = {};
}
}
async init() {
if (!this.initialized) return;
this._initPermanentEventListeners();
await this.loadCurrentSettings();
this._initSettingsModal();
await this.loadGroupsOnce();
this.state.currentView = null;
this.switchToView('error');
}
_initSettingsModal() {
if (!this.elements.settingsBtn) return;
this.settingsModal = new LogSettingsModal({
onSave: this.handleSaveSettings.bind(this)
});
this.elements.settingsBtn.addEventListener('click', () => {
const settingsForModal = {
log_level: this.currentSettings.log_level,
auto_cleanup: {
enabled: this.currentSettings.log_auto_cleanup_enabled,
retention_days: this.currentSettings.log_auto_cleanup_retention_days,
exec_time: this.currentSettings.log_auto_cleanup_time,
interval: 'daily',
}
};
this.settingsModal.open(settingsForModal);
});
}
async loadCurrentSettings() {
try {
const { success, data } = await apiFetchJson('/admin/settings');
if (success) {
this.currentSettings = data;
} else {
console.error('Failed to load settings from server.');
this.currentSettings = { log_auto_cleanup_time: '04:05' };
}
} catch (error) {
console.error('Failed to load log settings:', error);
this.currentSettings = { log_auto_cleanup_time: '04:05' };
}
}
async handleSaveSettings(settingsData) {
const partialPayload = {
"log_level": settingsData.log_level,
"log_auto_cleanup_enabled": settingsData.auto_cleanup.enabled,
"log_auto_cleanup_time": settingsData.auto_cleanup.exec_time,
};
if (settingsData.auto_cleanup.enabled) {
let retentionDays = settingsData.auto_cleanup.retention_days;
if (retentionDays === null || retentionDays <= 0) {
retentionDays = 30;
}
partialPayload.log_auto_cleanup_retention_days = retentionDays;
}
console.log('Sending PARTIAL settings update to /admin/settings:', partialPayload);
try {
const { success, message } = await apiFetchJson('/admin/settings', {
method: 'PUT',
body: JSON.stringify(partialPayload)
});
if (!success) {
throw new Error(message || 'Failed to save settings');
}
Object.assign(this.currentSettings, partialPayload);
} catch (error) {
console.error('Error saving log settings:', error);
throw error;
}
}
_initPermanentEventListeners() {
this.elements.tabsContainer.addEventListener('click', (event) => {
const tabItem = event.target.closest('[data-tab-target]');
@@ -68,6 +142,7 @@ class LogsPage {
}
});
}
switchToView(viewName) {
if (this.state.currentView === viewName && this.elements.contentContainer.innerHTML !== '') return;
if (this.systemLogTerminal) {
@@ -147,7 +222,6 @@ class LogsPage {
});
this.themeObserver.observe(document.documentElement, { attributes: true });
// 确保初始状态正确
applyTheme();
}
@@ -218,7 +292,6 @@ class LogsPage {
}
},
onReady: (selectedDates, dateStr, instance) => {
// 暗黑模式和清除按钮的现有逻辑保持不变
if (document.documentElement.classList.contains('dark')) {
instance.calendarContainer.classList.add('dark');
}
@@ -431,6 +504,7 @@ class LogsPage {
console.error("Failed to load key groups:", error);
}
}
async loadAndRenderLogs() {
this.state.isLoading = true;
this.state.selectedLogIds.clear();
@@ -500,7 +574,7 @@ class LogsPage {
}
async enrichLogsWithKeyNames(logs) {
const missingKeyIds = [...new Set(
logs.filter(log => log.KeyID && !dataStore.keys.has(log.KeyID)).map(log => log.ID)
logs.filter(log => log.KeyID && !dataStore.keys.has(log.KeyID)).map(log => log.KeyID)
)];
if (missingKeyIds.length === 0) return;
try {
@@ -514,7 +588,8 @@ class LogsPage {
}
}
}
export default function() {
const page = new LogsPage();
page.init();
}
}