/**
* 日志查看页面
*/
import { api } from '../lib/tauri-api.js'
import { toast } from '../components/toast.js'
const LOG_TABS = [
{ key: 'gateway', label: 'Gateway 日志' },
{ key: 'gateway-err', label: 'Gateway 错误' },
{ key: 'guardian', label: '守护进程' },
{ key: 'guardian-backup', label: '备份日志' },
{ key: 'config-audit', label: '审计日志' },
]
let _searchTimer = null
export async function render() {
const page = document.createElement('div')
page.className = 'page'
page.innerHTML = `
${LOG_TABS.map((t, i) => `
${t.label}
`).join('')}
`
let currentTab = 'gateway'
// Tab 切换
page.querySelectorAll('.tab').forEach(tab => {
tab.onclick = () => {
page.querySelectorAll('.tab').forEach(t => t.classList.remove('active'))
tab.classList.add('active')
currentTab = tab.dataset.tab
page.querySelector('#log-search').value = ''
loadLog(page, currentTab)
}
})
// 搜索
page.querySelector('#log-search').addEventListener('input', (e) => {
clearTimeout(_searchTimer)
_searchTimer = setTimeout(() => {
if (e.target.value.trim()) {
searchLog(page, currentTab, e.target.value.trim())
} else {
loadLog(page, currentTab)
}
}, 300)
})
// 刷新
page.querySelector('#btn-refresh').onclick = () => loadLog(page, currentTab)
loadLog(page, currentTab)
return page
}
export function cleanup() {
clearTimeout(_searchTimer)
_searchTimer = null
}
async function loadLog(page, logName) {
const el = page.querySelector('#log-content')
try {
const content = await api.readLogTail(logName, 200)
if (!content || !content.trim()) {
el.innerHTML = '暂无日志
'
return
}
const lines = content.trim().split('\n')
el.innerHTML = lines.map(l => `${escapeHtml(l)}
`).join('')
if (page.querySelector('#log-autoscroll')?.checked) {
el.scrollTop = el.scrollHeight
}
} catch (e) {
el.innerHTML = '加载日志失败: ' + e + '
'
toast('加载日志失败: ' + e, 'error')
}
}
async function searchLog(page, logName, query) {
const el = page.querySelector('#log-content')
try {
const results = await api.searchLog(logName, query)
if (!results || !results.length) {
el.innerHTML = '未找到匹配结果
'
return
}
el.innerHTML = results.map(l => `${highlightMatch(escapeHtml(l), query)}
`).join('')
} catch (e) {
el.innerHTML = '搜索失败: ' + e + '
'
toast('搜索失败: ' + e, 'error')
}
}
function escapeHtml(str) {
return str.replace(/&/g, '&').replace(//g, '>')
}
function highlightMatch(html, query) {
const escaped = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
return html.replace(new RegExp(escaped, 'gi'), m => `${m}`)
}