feat: 初始提交(仅核心代码,已排除大文件)
This commit is contained in:
@@ -0,0 +1,440 @@
|
||||
const state = { uid: '7716940453', mode: 'any', query: '', terms: [], count: 50 }
|
||||
const wbOut = document.getElementById('wb-debug-output')
|
||||
const wbBtnCopy = document.getElementById('wb-btn-copy')
|
||||
const wbBtnRefresh = document.getElementById('wb-btn-refresh')
|
||||
const wbBtnClear = document.getElementById('wb-btn-clear')
|
||||
|
||||
const wbRender = lines => {
|
||||
if (!wbOut) return
|
||||
wbOut.textContent = lines.join('\n')
|
||||
wbOut.scrollTop = wbOut.scrollHeight
|
||||
}
|
||||
|
||||
const wbLoad = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/debug/logs?limit=5000&channel=weibo')
|
||||
const data = await res.json()
|
||||
if (data.ok) wbRender(data.lines)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const ts = () => new Date().toISOString()
|
||||
const logLocal = msg => {
|
||||
if (!wbOut) return
|
||||
const line = `${ts()} ${msg}`
|
||||
const current = wbOut.textContent || ''
|
||||
wbOut.textContent = current ? current + "\n" + line : line
|
||||
wbOut.scrollTop = wbOut.scrollHeight
|
||||
}
|
||||
|
||||
const renderPosts = rows => {
|
||||
const box = el('fetch-results')
|
||||
box.innerHTML = ''
|
||||
for (const r of rows) {
|
||||
const card = document.createElement('div')
|
||||
card.className = 'card'
|
||||
const meta = document.createElement('div')
|
||||
meta.className = 'meta'
|
||||
meta.textContent = `${r.screen_name || ''} · ${r.created_at || ''}`
|
||||
const text = document.createElement('div')
|
||||
text.innerHTML = highlight(r.text || '', state.terms)
|
||||
const link = document.createElement('a')
|
||||
link.href = (r.retweeted_url || r.url || '#')
|
||||
link.target = '_blank'
|
||||
link.textContent = '打开原文'
|
||||
if (r.retweeted_text) {
|
||||
const rt = document.createElement('div')
|
||||
rt.className = 'meta'
|
||||
rt.innerHTML = `↪ 原博 ${r.retweeted_screen_name || ''}: ` + highlight(r.retweeted_text || '', state.terms)
|
||||
card.appendChild(rt)
|
||||
}
|
||||
const stat = document.createElement('div')
|
||||
stat.className = 'meta'
|
||||
stat.textContent = `转发:${r.reposts_count} 评论:${r.comments_count} 赞:${r.attitudes_count}`
|
||||
card.appendChild(meta)
|
||||
card.appendChild(text)
|
||||
card.appendChild(link)
|
||||
card.appendChild(stat)
|
||||
box.appendChild(card)
|
||||
}
|
||||
}
|
||||
|
||||
const setResultsMeta = text => {
|
||||
const m = document.getElementById('results-meta')
|
||||
if (m) m.textContent = String(text || '')
|
||||
}
|
||||
|
||||
const fetchLatest = async () => {
|
||||
const uid = el('input-uid').value.trim()
|
||||
logLocal(`frontend.event {"source":"weibo","action":"fetch.click","uid":"${uid}"}`)
|
||||
try { await fetch('/api/debug/event', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ source: 'weibo', action: 'fetch.click', uid }) }) } catch {}
|
||||
wbLoad()
|
||||
const statusBox = document.getElementById('status')
|
||||
if (statusBox) { statusBox.style.display = ''; statusBox.textContent = `正在拉取最近${state.count}条...` }
|
||||
const res = await fetch(`/api/weibo/${uid}/fetch?count=${encodeURIComponent(state.count || 50)}`)
|
||||
const data = await res.json()
|
||||
if (!data.ok) {
|
||||
logLocal(`weibo.fetch.error ${JSON.stringify({ error: data.error })}`)
|
||||
if (statusBox) statusBox.textContent = (data.hint ? data.hint + '。' : '') + (data.error || '拉取失败')
|
||||
alert(`拉取失败:${String(data.error || 'unknown')}`)
|
||||
} else {
|
||||
logLocal(`weibo.fetch.done ${JSON.stringify({ uid, fetched: data.fetched })}`)
|
||||
if (statusBox) { statusBox.style.display = 'none'; statusBox.textContent = '' }
|
||||
alert(`本次拉取:${data.fetched || 0} 条`)
|
||||
const latestBox = document.getElementById('latest-data-time'); if (latestBox) latestBox.value = String(data.latest_time || '')
|
||||
const sourceMap = { devtools: 'DevTools', settings: '设置Cookie', anonymous: '匿名Cookie', '': '未知' }
|
||||
const srcLabel = sourceMap[String(data.source || '')] || '未知'
|
||||
const rows = Array.isArray(data.rows) ? data.rows : []
|
||||
renderPosts(rows)
|
||||
setResultsMeta(`数据来源:${srcLabel} · 仅显示本次拉取结果 · 当前 ${rows.length} 条`)
|
||||
}
|
||||
wbLoad()
|
||||
return data
|
||||
}
|
||||
|
||||
const renderAll = async (q = '', mode = 'any') => {
|
||||
const uid = el('input-uid').value.trim()
|
||||
state.mode = mode
|
||||
state.query = q
|
||||
state.terms = q ? q.split(/\s+/).filter(Boolean) : []
|
||||
logLocal(`frontend.event ${JSON.stringify({ source:'weibo', action:'kw.search', uid, mode, terms: state.terms })}`)
|
||||
const res = await fetch(`/api/weibo/search?uid=${encodeURIComponent(uid)}&q=${encodeURIComponent(q)}&mode=${encodeURIComponent(mode)}&limit=50`)
|
||||
const data = await res.json()
|
||||
if (data.ok) { renderPosts(data.rows); logLocal(`frontend.event ${JSON.stringify({ source:'weibo', action:'kw.search.done', count: (data.rows||[]).length })}`); return data.rows || [] }
|
||||
return []
|
||||
}
|
||||
|
||||
const matches = (text, terms, mode) => {
|
||||
if (!terms || terms.length === 0) return true
|
||||
const checks = terms.map(t => new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i').test(text))
|
||||
return mode === 'all' ? checks.every(Boolean) : checks.some(Boolean)
|
||||
}
|
||||
const loadArchiveToPanel = async () => {
|
||||
const uid = el('input-uid').value.trim()
|
||||
const start = el('arch-week-start').value
|
||||
const end = el('arch-week-end').value
|
||||
const res = await fetch(`/api/archives/get?uid=${encodeURIComponent(uid)}&start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}`)
|
||||
const data = await res.json()
|
||||
if (data.ok) el('archive-results').innerHTML = data.html || ''
|
||||
}
|
||||
const searchArchive = async () => {
|
||||
const q = el('arch-query').value.trim()
|
||||
const mode = el('arch-mode').value
|
||||
const terms = q ? q.split(/\s+/).filter(Boolean) : []
|
||||
const cards = Array.from(document.querySelectorAll('#archive-results .card'))
|
||||
if (cards.length === 0) return
|
||||
cards.forEach(card => {
|
||||
const text = card.textContent || ''
|
||||
const show = matches(text, terms, mode)
|
||||
card.style.display = show ? '' : 'none'
|
||||
if (show) card.innerHTML = highlight(card.innerHTML, terms)
|
||||
})
|
||||
}
|
||||
|
||||
const openSettings = () => { el('settings-modal').classList.remove('hidden') }
|
||||
const closeSettings = () => {
|
||||
const closeBtn = el('btn-close-settings')
|
||||
if (closeBtn) {
|
||||
closeBtn.classList.add('warning')
|
||||
setTimeout(() => {
|
||||
closeBtn.classList.remove('warning')
|
||||
el('settings-modal').classList.add('hidden')
|
||||
}, 300)
|
||||
} else {
|
||||
el('settings-modal').classList.add('hidden')
|
||||
}
|
||||
}
|
||||
|
||||
const saveSettings = async () => {
|
||||
const saveBtn = el('btn-save-settings')
|
||||
|
||||
// 添加保存动画效果
|
||||
if (saveBtn) {
|
||||
saveBtn.classList.add('saving')
|
||||
saveBtn.disabled = true
|
||||
saveBtn.textContent = '保存中...'
|
||||
}
|
||||
|
||||
const uid = el('settings-uid').value.trim()
|
||||
const countVal = parseInt((document.getElementById('settings-count').value || '50'), 10)
|
||||
const kwRaw = el('settings-keywords').value.trim()
|
||||
const keywords = kwRaw.split('|').map(s => s.trim()).filter(Boolean)
|
||||
const body = { users: [{ uid, screen_name: '' }], keywords, headers: {}, count: countVal }
|
||||
|
||||
logLocal(`frontend.event ${JSON.stringify({ source: 'weibo', action: 'settings.save', uid, keywordsCount: keywords.length })}`)
|
||||
|
||||
try {
|
||||
await fetch('/api/debug/event', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ source: 'weibo', action: 'settings.save', uid, keywordsCount: keywords.length })
|
||||
})
|
||||
} catch {}
|
||||
|
||||
await fetch('/api/settings', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
|
||||
// 恢复按钮状态
|
||||
if (saveBtn) {
|
||||
setTimeout(() => {
|
||||
saveBtn.classList.remove('saving')
|
||||
saveBtn.disabled = false
|
||||
saveBtn.textContent = '保存'
|
||||
|
||||
// 添加成功确认效果
|
||||
saveBtn.style.background = 'linear-gradient(135deg, #00ff00, #00cc00)'
|
||||
setTimeout(() => {
|
||||
saveBtn.style.background = 'linear-gradient(135deg, var(--primary), var(--secondary))'
|
||||
closeSettings()
|
||||
}, 500)
|
||||
}, 1000)
|
||||
} else {
|
||||
closeSettings()
|
||||
}
|
||||
|
||||
wbLoad()
|
||||
state.count = countVal
|
||||
const b = document.getElementById('btn-fetch')
|
||||
if (b) b.textContent = `拉取最近${state.count}条`
|
||||
}
|
||||
|
||||
const loadSettings = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/settings')
|
||||
const data = await res.json()
|
||||
const cfg = (data && data.file) || {}
|
||||
const uid = (cfg.users && cfg.users[0] && cfg.users[0].uid) ? String(cfg.users[0].uid) : (state.uid || '')
|
||||
const count = parseInt(String(cfg.count || state.count), 10)
|
||||
const kw = Array.isArray(cfg.keywords) ? cfg.keywords.join('|') : ''
|
||||
const iu = document.getElementById('input-uid'); if (iu) iu.value = uid
|
||||
const su = document.getElementById('settings-uid'); if (su) su.value = uid
|
||||
const sc = document.getElementById('settings-count'); if (sc) sc.value = String(count)
|
||||
const sk = document.getElementById('settings-keywords'); if (sk) sk.value = kw
|
||||
|
||||
state.uid = uid
|
||||
state.count = count
|
||||
const b = document.getElementById('btn-fetch'); if (b) b.textContent = `拉取最近${state.count}条`
|
||||
renderKeywordChips(Array.isArray(cfg.keywords) ? cfg.keywords : [])
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const truncateLabel = (s, n = 8) => {
|
||||
const str = String(s || '')
|
||||
return str.length > n ? (str.slice(0, n) + '...') : str
|
||||
}
|
||||
|
||||
const renderKeywordChips = (keywords) => {
|
||||
try {
|
||||
const panelArchive = document.getElementById('panel-archive')
|
||||
let archHolder = document.getElementById('arch-chips')
|
||||
if (!archHolder && panelArchive) { archHolder = document.createElement('div'); archHolder.id = 'arch-chips'; archHolder.className = 'chips'; panelArchive.insertBefore(archHolder, panelArchive.firstChild) }
|
||||
if (archHolder) archHolder.innerHTML = ''
|
||||
const groups = (keywords || []).map(k => String(k || '').trim()).filter(Boolean)
|
||||
for (const g of groups) {
|
||||
const btn = document.createElement('button'); btn.className = 'chip'; btn.dataset.q = g; btn.textContent = truncateLabel(g, 8)
|
||||
btn.style.margin = '0 6px 6px 0'
|
||||
btn.addEventListener('click', () => { const iq = document.getElementById('arch-query'); if (iq) iq.value = g; searchArchive() })
|
||||
if (archHolder) archHolder.appendChild(btn)
|
||||
}
|
||||
// ensure no stray chips remain in fetch panel
|
||||
Array.from(document.querySelectorAll('#panel-fetch .chip')).forEach(ch => ch.remove())
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// 创建粒子效果
|
||||
function createParticles() {
|
||||
const container = document.getElementById('particles-container')
|
||||
if (!container) return
|
||||
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const particle = document.createElement('div')
|
||||
particle.className = 'particle'
|
||||
particle.style.left = Math.random() * 100 + '%'
|
||||
particle.style.animationDelay = Math.random() * 6 + 's'
|
||||
particle.style.animationDuration = (Math.random() * 3 + 4) + 's'
|
||||
container.appendChild(particle)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加霓虹灯效果到输入框
|
||||
function addNeonEffects() {
|
||||
const inputs = document.querySelectorAll('input[type="text"], input[type="date"], select')
|
||||
inputs.forEach(input => {
|
||||
input.classList.add('neon-input')
|
||||
|
||||
// 添加焦点效果
|
||||
input.addEventListener('focus', function() {
|
||||
this.style.boxShadow = '0 0 20px rgba(0, 255, 255, 0.5), 0 0 40px rgba(0, 255, 255, 0.3)'
|
||||
})
|
||||
|
||||
input.addEventListener('blur', function() {
|
||||
this.style.boxShadow = '0 0 10px rgba(255, 20, 147, 0.3)'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 添加按钮特殊效果
|
||||
function enhanceButtons() {
|
||||
const specialButtons = ['btn-fetch', 'btn-save-week', 'arch-search']
|
||||
specialButtons.forEach(id => {
|
||||
const btn = document.getElementById(id)
|
||||
if (btn) {
|
||||
btn.classList.add('btn-special')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
try {
|
||||
// 初始化视觉效果
|
||||
createParticles()
|
||||
addNeonEffects()
|
||||
enhanceButtons()
|
||||
|
||||
logLocal('frontend.event {"source":"weibo","action":"dom.ready"}')
|
||||
const bf = el('btn-fetch'); if (bf) bf.addEventListener('click', async () => { await fetchLatest() })
|
||||
const bs = el('btn-search'); if (bs) bs.addEventListener('click', searchPosts)
|
||||
const bset = el('btn-settings'); if (bset) bset.addEventListener('click', openSettings)
|
||||
const bclose = el('btn-close-settings'); if (bclose) bclose.addEventListener('click', closeSettings)
|
||||
const bsave = el('btn-save-settings'); if (bsave) bsave.addEventListener('click', saveSettings)
|
||||
|
||||
const dStart = document.getElementById('week-start')
|
||||
const dEnd = document.getElementById('week-end')
|
||||
const btnSaveWeek = document.getElementById('btn-save-week')
|
||||
const btnWeekPrev = document.getElementById('btn-week-prev')
|
||||
const btnWeekCurrent = document.getElementById('btn-week-current')
|
||||
const btnWeekNext = document.getElementById('btn-week-next')
|
||||
|
||||
const fmt = d => {
|
||||
const y = d.getFullYear()
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
const weekRangeFromDate = anchor => {
|
||||
const d = new Date(anchor)
|
||||
const dow = d.getDay()
|
||||
const shift = dow === 0 ? -6 : 1 - dow
|
||||
const start = new Date(d.getFullYear(), d.getMonth(), d.getDate() + shift)
|
||||
const end = new Date(start.getFullYear(), start.getMonth(), start.getDate() + 6)
|
||||
return { start, end }
|
||||
}
|
||||
const setWeek = anchor => {
|
||||
const r = weekRangeFromDate(anchor)
|
||||
dStart.value = fmt(r.start)
|
||||
dEnd.value = fmt(r.end)
|
||||
}
|
||||
const saveArchive = async () => {
|
||||
const uid = el('input-uid').value.trim()
|
||||
const content = el('fetch-results').innerHTML
|
||||
const header = `<div class="meta">封存范围:${dStart.value} 至 ${dEnd.value} · UID ${uid}</div>`
|
||||
const html = `<article class="archive">${header}${content}</article>`
|
||||
await fetch('/api/archives/save', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ uid, start: dStart.value, end: dEnd.value, html }) })
|
||||
logLocal(`frontend.event ${JSON.stringify({ source: 'weibo', action: 'archive.save', uid, start: dStart.value, end: dEnd.value, html_len: html.length })}`)
|
||||
}
|
||||
if (btnSaveWeek) btnSaveWeek.addEventListener('click', saveArchive)
|
||||
if (btnWeekPrev) btnWeekPrev.addEventListener('click', () => { const s = new Date(dStart.value); s.setDate(s.getDate() - 7); setWeek(s) })
|
||||
if (btnWeekCurrent) btnWeekCurrent.addEventListener('click', () => { setWeek(new Date()) })
|
||||
if (btnWeekNext) btnWeekNext.addEventListener('click', () => { const s = new Date(dStart.value); s.setDate(s.getDate() + 7); setWeek(s) })
|
||||
setWeek(new Date())
|
||||
// Archive panel controls
|
||||
const archStart = document.getElementById('arch-week-start')
|
||||
const archEnd = document.getElementById('arch-week-end')
|
||||
const archPrev = document.getElementById('arch-week-prev')
|
||||
const archCurr = document.getElementById('arch-week-current')
|
||||
const archNext = document.getElementById('arch-week-next')
|
||||
const setArchWeek = anchor => { const r = weekRangeFromDate(anchor); archStart.value = fmt(r.start); archEnd.value = fmt(r.end) }
|
||||
if (archPrev) archPrev.addEventListener('click', async () => { const s = new Date(archStart.value); s.setDate(s.getDate() - 7); setArchWeek(s); await loadArchiveToPanel() })
|
||||
if (archCurr) archCurr.addEventListener('click', async () => { setArchWeek(new Date()); await loadArchiveToPanel() })
|
||||
if (archNext) archNext.addEventListener('click', async () => { const s = new Date(archStart.value); s.setDate(s.getDate() + 7); setArchWeek(s); await loadArchiveToPanel() })
|
||||
const archSearchBtn = document.getElementById('arch-search')
|
||||
if (archSearchBtn) archSearchBtn.addEventListener('click', searchArchive)
|
||||
const archReset = document.getElementById('arch-reset')
|
||||
if (archReset) archReset.addEventListener('click', async () => { el('arch-query').value = ''; const m=document.getElementById('arch-mode'); if (m) m.value='any'; await loadArchiveToPanel() })
|
||||
document.querySelectorAll('#panel-archive .chip').forEach(b => { b.addEventListener('click', () => { el('arch-query').value = b.dataset.q || ''; searchArchive() }) })
|
||||
// Subtabs
|
||||
const tabFetch = document.getElementById('tab-fetch')
|
||||
const tabArchive = document.getElementById('tab-archive')
|
||||
const tabPreview = document.getElementById('tab-preview')
|
||||
const panelFetch = document.getElementById('panel-fetch')
|
||||
const panelArchive = document.getElementById('panel-archive')
|
||||
const panelPreview = document.getElementById('panel-preview')
|
||||
const previewUrlInput = document.getElementById('preview-url')
|
||||
const previewOpen = document.getElementById('preview-open')
|
||||
const previewFrame = document.getElementById('preview-frame')
|
||||
|
||||
const computePreviewUrl = () => {
|
||||
const uid = el('input-uid').value.trim()
|
||||
return `https://m.weibo.cn/u/${uid}`
|
||||
}
|
||||
const loadPreview = async () => {
|
||||
const url = (previewUrlInput && previewUrlInput.value.trim()) || computePreviewUrl()
|
||||
if (previewUrlInput) previewUrlInput.value = url
|
||||
if (previewOpen) previewOpen.href = url
|
||||
if (previewFrame) previewFrame.src = url
|
||||
logLocal(`frontend.event ${JSON.stringify({ source:'weibo', action:'preview.iframe', url })}`)
|
||||
}
|
||||
const activate = async (name) => {
|
||||
if (name === 'fetch') {
|
||||
panelFetch.style.display = ''
|
||||
panelArchive.style.display = 'none'
|
||||
panelPreview.style.display = 'none'
|
||||
tabFetch.classList.add('active'); tabArchive.classList.remove('active'); if (tabPreview) tabPreview.classList.remove('active')
|
||||
} else if (name === 'archive') {
|
||||
panelFetch.style.display = 'none'
|
||||
panelArchive.style.display = ''
|
||||
panelPreview.style.display = 'none'
|
||||
tabArchive.classList.add('active'); tabFetch.classList.remove('active'); if (tabPreview) tabPreview.classList.remove('active')
|
||||
} else if (name === 'preview') {
|
||||
panelFetch.style.display = 'none'
|
||||
panelArchive.style.display = 'none'
|
||||
panelPreview.style.display = ''
|
||||
if (tabPreview) tabPreview.classList.add('active'); tabFetch.classList.remove('active'); tabArchive.classList.remove('active')
|
||||
await loadSettings()
|
||||
if (previewUrlInput) previewUrlInput.value = computePreviewUrl()
|
||||
if (previewOpen) previewOpen.href = computePreviewUrl()
|
||||
await loadPreview()
|
||||
}
|
||||
}
|
||||
if (tabFetch) tabFetch.addEventListener('click', async () => { await activate('fetch'); clearFetchCache(); await checkDevtools() })
|
||||
if (tabArchive) tabArchive.addEventListener('click', () => activate('archive'))
|
||||
if (tabPreview) tabPreview.addEventListener('click', () => activate('preview'))
|
||||
if (previewUrlInput) previewUrlInput.addEventListener('change', loadPreview)
|
||||
if (previewUrlInput) previewUrlInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') loadPreview() })
|
||||
if (wbBtnCopy) wbBtnCopy.addEventListener('click', async () => { try { await navigator.clipboard.writeText(wbOut.textContent || '') } catch {} })
|
||||
if (wbBtnRefresh) wbBtnRefresh.addEventListener('click', wbLoad)
|
||||
if (wbBtnClear) wbBtnClear.addEventListener('click', async () => { try { await fetch('/api/debug/clear?channel=weibo', { method: 'POST' }) } catch {}; wbLoad() })
|
||||
setInterval(wbLoad, 5000)
|
||||
wbLoad()
|
||||
await loadSettings()
|
||||
setWeek(new Date())
|
||||
setArchWeek(new Date())
|
||||
const clearFetchCache = () => {
|
||||
const box = el('fetch-results'); if (box) box.innerHTML = ''
|
||||
alert('缓存已清理,当前无数据状态')
|
||||
logLocal('frontend.event {"source":"weibo","action":"cache.cleared"}')
|
||||
}
|
||||
const checkDevtools = async () => {
|
||||
try {
|
||||
const ds = await fetch('/api/weibo/devtools/status')
|
||||
const dj = await ds.json()
|
||||
if (dj && dj.ok && dj.connected) alert('已对接服务器 Chrome DevTools')
|
||||
else alert('未对接服务器 Chrome DevTools,请在服务器Chrome登录微博并开启9222端口')
|
||||
logLocal(`frontend.event ${JSON.stringify({ source:'weibo', action:'devtools.status', ok: !!(dj && dj.ok), connected: !!(dj && dj.connected) })}`)
|
||||
} catch (e) {
|
||||
alert('未能获取 DevTools 状态')
|
||||
logLocal(`frontend.event ${JSON.stringify({ source:'weibo', action:'devtools.error', error: String(e.message||e) })}`)
|
||||
}
|
||||
}
|
||||
const isFetchActive = tabFetch && tabFetch.classList.contains('active')
|
||||
if (isFetchActive) {
|
||||
clearFetchCache()
|
||||
await checkDevtools()
|
||||
}
|
||||
} catch (e) {
|
||||
logLocal(`frontend.error ${String(e && e.message ? e.message : e)}`)
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user