feat(forum): rebuild forum home page
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
51d5b8a2a1
commit
024ecddfed
16 files changed
+1061
-198
No files matched your search
+102
-15
@@ -23,8 +23,7 @@
|
||||
else if (value) window.alert(value)
|
||||
}
|
||||
|
||||
const modal = (title, fields, submitText = '确认') => new Promise((resolve) => {
|
||||
const dialog = document.createElement('dialog')
|
||||
const modal = (title, fields, submitText = '确认') => new Promise((resolve) => { const dialog = document.createElement('dialog')
|
||||
dialog.className = 'jio-forum__dialog'
|
||||
const form = document.createElement('form')
|
||||
form.innerHTML = '<h2></h2><div class="jio-forum__dialog-fields"></div><div class="jio-forum__dialog-actions"><button type="button" data-cancel>取消</button><button type="submit" class="jio-forum__primary"></button></div>'
|
||||
@@ -172,7 +171,13 @@
|
||||
return
|
||||
}
|
||||
const open = event.target.closest('[data-forum-open]')
|
||||
if (open) { root.querySelector(`[data-forum-dialog="${open.dataset.forumOpen}"]`)?.showModal(); return }
|
||||
if (open) {
|
||||
const dialog = root.querySelector(`[data-forum-dialog="${open.dataset.forumOpen}"]`)
|
||||
const category = dialog?.querySelector('select[name="category_id"]')
|
||||
if (category && open.dataset.category) category.value = open.dataset.category
|
||||
dialog?.showModal()
|
||||
return
|
||||
}
|
||||
const close = event.target.closest('[data-forum-close]')
|
||||
if (close) { close.closest('dialog')?.close(); return }
|
||||
const reply = event.target.closest('[data-forum-reply-to]')
|
||||
@@ -193,7 +198,7 @@
|
||||
if (action === 'plate-unlock') { await checkout('plate', id); return }
|
||||
if (action === 'plate-audit') {
|
||||
result = await send(`plates/${id}/audit`, 'POST', { status: 'publish' })
|
||||
button.closest('.jio-forum__pending > div')?.remove()
|
||||
button.closest('.forum-pending-plate')?.remove()
|
||||
} else if (action === 'plate-delete') {
|
||||
const data = await modal('删除版块', [
|
||||
{ name: 'posts_action', label: '关联帖子', type: 'select', options: [{ value: 'trash', label: '一并移入回收站' }, { value: 'move', label: '移动到其他版块' }] },
|
||||
@@ -213,16 +218,6 @@
|
||||
if (!window.confirm('确定删除此回复?')) return
|
||||
result = await send(`replies/${id}/delete`, 'POST')
|
||||
button.closest('.jio-forum__reply')?.remove()
|
||||
} else if (action === 'term-edit') {
|
||||
const name = button.closest('.jio-forum__term-row')?.querySelector('span')?.textContent || ''
|
||||
const data = await modal('编辑分类', [{ name: 'name', label: '名称', value: name }], '保存')
|
||||
if (!data) return
|
||||
result = await send(`terms/${id}`, 'PATCH', data)
|
||||
button.closest('.jio-forum__term-row').querySelector('span').textContent = data.name
|
||||
} else if (action === 'term-delete') {
|
||||
if (!window.confirm('确定删除这个分类?')) return
|
||||
result = await send(`terms/${id}`, 'DELETE')
|
||||
button.closest('.jio-forum__term-row')?.remove()
|
||||
} else if (action === 'follow') {
|
||||
try { result = await send(`plates/${id}/follow`, 'POST') }
|
||||
catch (error) { if (error.message.includes('付费')) { await checkout('plate', id); return } throw error }
|
||||
@@ -254,7 +249,17 @@
|
||||
button.dataset.forumAction = 'restore'
|
||||
button.textContent = '撤销删除'
|
||||
} else if (action === 'adopt' || action === 'audit') window.location.reload()
|
||||
else button.textContent = result.data?.label || result.message || button.textContent
|
||||
else if (action === 'follow') {
|
||||
const following = result.data?.following === true
|
||||
button.classList.toggle('active', following)
|
||||
const label = button.querySelector('text')
|
||||
if (label) label.textContent = following ? '已关注' : '关注'
|
||||
else button.textContent = result.data?.label || button.textContent
|
||||
} else if (button.querySelector('text')) {
|
||||
button.querySelector('text').textContent = result.data?.label || result.message || button.querySelector('text').textContent
|
||||
} else {
|
||||
button.textContent = result.data?.label || result.message || button.textContent
|
||||
}
|
||||
message(button, result.message || '')
|
||||
} catch (error) {
|
||||
message(button, error.message)
|
||||
@@ -263,4 +268,86 @@
|
||||
button.disabled = false
|
||||
}
|
||||
})
|
||||
|
||||
// 论坛首页栏目:点击切换 + 懒加载该栏目的 ajaxpager 内容
|
||||
const refresh = (pane) => {
|
||||
if (typeof window.auto_fun === 'function') window.auto_fun()
|
||||
if (typeof window.jioInitForumMedia === 'function') window.jioInitForumMedia(pane)
|
||||
}
|
||||
|
||||
const loadTab = async (pane, href) => {
|
||||
if (!pane || pane.dataset.loaded === '1' || pane.dataset.loading === '1') return
|
||||
pane.dataset.loading = '1'
|
||||
pane.querySelector('.post_ajax_loader')?.classList.add('is-loading')
|
||||
try {
|
||||
const response = await fetch(href, { credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
||||
if (!response.ok) throw new Error('加载失败')
|
||||
const doc = new DOMParser().parseFromString(await response.text(), 'text/html')
|
||||
const source = doc.getElementById(pane.id)
|
||||
if (!source) throw new Error('内容不存在')
|
||||
pane.innerHTML = source.innerHTML
|
||||
pane.dataset.loaded = '1'
|
||||
refresh(pane)
|
||||
} catch (error) {
|
||||
pane.querySelector('.post_ajax_loader')?.classList.remove('is-loading')
|
||||
message(pane, error.message)
|
||||
} finally {
|
||||
pane.dataset.loading = ''
|
||||
}
|
||||
}
|
||||
|
||||
const loadMore = async (link, pane) => {
|
||||
if (pane.dataset.loading === '1') return
|
||||
pane.dataset.loading = '1'
|
||||
const more = link.closest('.forum-more')
|
||||
const loader = [...pane.children].find((item) => item.classList.contains('post_ajax_loader'))
|
||||
more?.classList.add('is-loading')
|
||||
loader?.classList.add('is-loading')
|
||||
try {
|
||||
const response = await fetch(link.getAttribute('href'), { credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
||||
if (!response.ok) throw new Error('加载失败')
|
||||
const doc = new DOMParser().parseFromString(await response.text(), 'text/html')
|
||||
const source = doc.getElementById(pane.id)
|
||||
if (!source) throw new Error('内容不存在')
|
||||
const anchor = more || null
|
||||
const incoming = [...source.children].filter((item) => !item.classList.contains('forum-tab-pane') && !item.classList.contains('forum-more') && !item.classList.contains('post_ajax_loader'))
|
||||
incoming.forEach((item) => pane.insertBefore(item, anchor))
|
||||
const next = source.querySelector('[data-forum-more]')
|
||||
if (next && anchor) anchor.querySelector('[data-forum-more]')?.setAttribute('href', next.getAttribute('href'))
|
||||
else anchor?.remove()
|
||||
refresh(pane)
|
||||
} catch (error) {
|
||||
message(pane, error.message)
|
||||
} finally {
|
||||
pane.dataset.loading = ''
|
||||
more?.classList.remove('is-loading')
|
||||
loader?.classList.remove('is-loading')
|
||||
}
|
||||
}
|
||||
|
||||
root.addEventListener('click', (event) => {
|
||||
const tab = event.target.closest('[data-forum-tab]')
|
||||
if (tab) {
|
||||
event.preventDefault()
|
||||
const target = tab.getAttribute('data-forum-tab')
|
||||
const pane = root.querySelector(target)
|
||||
root.querySelectorAll('[data-forum-tab]').forEach((link) => link.closest('li')?.classList.toggle('active', link === tab))
|
||||
root.querySelectorAll('.forum-tab-pane').forEach((item) => {
|
||||
const current = `#${item.id}` === target
|
||||
item.classList.toggle('active', current)
|
||||
item.classList.toggle('in', current)
|
||||
})
|
||||
if (pane) {
|
||||
loadTab(pane, pane.dataset.href || tab.getAttribute('href'))
|
||||
if (pane.dataset.href && window.history?.replaceState) window.history.replaceState(null, document.title, pane.dataset.href)
|
||||
}
|
||||
return
|
||||
}
|
||||
const more = event.target.closest('[data-forum-more]')
|
||||
if (more) {
|
||||
event.preventDefault()
|
||||
const pane = more.closest('.forum-tab-pane')
|
||||
if (pane) loadMore(more, pane)
|
||||
}
|
||||
})
|
||||
})()
|
||||
Reference in new issue
Block a user