From ab08b1a2a9fc1a08d7d5017ca2160692819dcafe Mon Sep 17 00:00:00 2001 From: canglan Date: Thu, 16 Jul 2026 23:50:16 +0800 Subject: [PATCH] feat: feature discussion as separate detail page, not inline --- public/index.html | 1 + public/js/app.js | 2 ++ public/js/pages/feature-detail.js | 55 +++++++++++++++++++++++++++++++ public/js/pages/features.js | 14 ++------ 4 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 public/js/pages/feature-detail.js diff --git a/public/index.html b/public/index.html index 8b40180..c92f265 100644 --- a/public/index.html +++ b/public/index.html @@ -72,6 +72,7 @@ + diff --git a/public/js/app.js b/public/js/app.js index 33a8951..8c581b9 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -99,6 +99,7 @@ const App = { case 'export': this.renderMain('数据导出', ExportPage, param); break; case 'polls': this.renderMain('投票', PollsPage, param); break; case 'features': this.renderMain('更新内容', FeaturesPage, param); break; + case 'feature': this.renderMain('更新详情', FeatureDetail, param); break; case 'servers': this.renderMain('服务器管理', ServersPage, param); break; default: this.renderMain('控制台', Dashboard, param); } @@ -176,6 +177,7 @@ window.SettingsPage = SettingsPage; window.ExportPage = ExportPage; window.PollsPage = PollsPage; window.FeaturesPage = FeaturesPage; +window.FeatureDetail = FeatureDetail; window.ServersPage = ServersPage; window.LoginPage = LoginPage; window.RegisterPage = RegisterPage; diff --git a/public/js/pages/feature-detail.js b/public/js/pages/feature-detail.js new file mode 100644 index 0000000..eca150e --- /dev/null +++ b/public/js/pages/feature-detail.js @@ -0,0 +1,55 @@ +const FeatureDetail = { + id: null, + + async render(id) { this.id = id; return '
'; }, + + async mount() { + const id = this.id; + document.getElementById('page-title').textContent = `更新 #${id}`; + document.getElementById('page-actions').innerHTML = ''; + try { + const item = await API.get('/features/'+id); + this.renderDetail(item); + } catch(e) { document.getElementById('page-content').innerHTML = `
${e.message}
`; } + }, + + renderDetail(i) { + const sc = i.status==='done'?'var(--s)':i.status==='planned'?'var(--p)':'var(--g5)'; + const sl = i.status==='done'?'已完成':i.status==='planned'?'计划中':'待定'; + const ct = document.getElementById('page-content'); + ct.innerHTML = `
+ ${i.status==='done'?'\u2713':i.status==='planned'?'\u25C9':'\u25CB'} ${U.esc(i.title)} + ${sl} · ${i.votes_count||0} 票 +
+ ${i.description?`

${U.esc(i.description)}

`:''} + ${i.group_name?`${U.esc(i.group_name)}/${U.esc(i.server_name)}`:''} + ${U.date(i.created_at)} +
+ +
+
+ +
讨论 (${(i.comments||[]).length})
+
${(i.comments||[]).length===0?'

暂无讨论

':i.comments.map(c=>` +
+ ${U.esc(c.username||'用户')} ${c.role ? U.badge(c.role,'role') : ''} + ${U.date(c.created_at)} +
${U.esc(c.content)}
+
`).join('')} +
+
+ + +
+
`; + + document.getElementById('feat-detail-vote').onclick = async () => { + try { await API.post(`/features/${id}/vote`); this.mount(); } catch(ex){alert(ex.message);} + }; + document.getElementById('feat-comment-form').onsubmit = async e => { + e.preventDefault(); + const inp = document.getElementById('feat-comment-input'); + try { await API.post(`/features/${id}/comment`, {content:inp.value}); inp.value=''; this.mount(); } catch(ex){alert(ex.message);} + }; + } +}; diff --git a/public/js/pages/features.js b/public/js/pages/features.js index f665799..48f4513 100644 --- a/public/js/pages/features.js +++ b/public/js/pages/features.js @@ -65,10 +65,7 @@ const FeaturesPage = { const items = await API.get('/features?' + params); ct.innerHTML = items.length === 0 ? '

暂无内容

' : items.map(i => this.renderItem(i)).join(''); - for (const i of items) { - if (Auth.logged()) this.bindVote(i); - this.bindComment(i); - } + for (const i of items) { if (Auth.logged()) this.bindVote(i); } } catch (e) { ct.innerHTML = `
${e.message}
`; } }, @@ -77,7 +74,7 @@ const FeaturesPage = { const statusLabel = i.status==='done'?'已完成':i.status==='planned'?'计划中':'待定'; return `
- ${i.status==='done'?'\u2713':i.status==='planned'?'\u25C9':'\u25CB'} ${U.esc(i.title)} + ${i.status==='done'?'\u2713':i.status==='planned'?'\u25C9':'\u25CB'} ${U.esc(i.title)}
${i.group_name ? `${U.esc(i.group_name)}` : ''} ${Auth.isOwner() ? `` : ''} @@ -87,14 +84,9 @@ const FeaturesPage = { ${i.description ? `

${U.esc(i.description)}

` : ''}
- ${i.comments_count||0} 讨论 + ${i.comments_count||0} 讨论 ${U.date(i.created_at)}
- -
`; },