90 lines
4.7 KiB
JavaScript
90 lines
4.7 KiB
JavaScript
const FeaturesPage = {
|
|
async render() { return '<div class="loading"><i class="fas fa-spinner"></i></div>'; },
|
|
|
|
async mount() {
|
|
document.getElementById('page-title').textContent = '更新内容';
|
|
document.getElementById('page-actions').innerHTML = Auth.isOwner()
|
|
? '<button class="btn btn-p btn-sm" onclick="FeaturesPage.showCreate()"><i class="fas fa-plus"></i> 添加项目</button>'
|
|
: '';
|
|
await this.load();
|
|
},
|
|
|
|
async load() {
|
|
const ct = document.getElementById('page-content');
|
|
try {
|
|
const items = await API.get('/features');
|
|
ct.innerHTML = items.length === 0
|
|
? '<div class="empty"><i class="fas fa-lightbulb"></i><p>暂无更新项目</p></div>'
|
|
: items.map(i => this.renderItem(i)).join('');
|
|
for (const i of items) if (Auth.logged() || Auth.logged()) this.bindVote(i);
|
|
} catch (e) { ct.innerHTML = `<div class="alert alert-e">${e.message}</div>`; }
|
|
},
|
|
|
|
renderItem(i) {
|
|
const statusColor = i.status === 'done' ? 'var(--s)' : i.status === 'planned' ? 'var(--p)' : 'var(--g5)';
|
|
const statusLabel = i.status === 'done' ? '已完成' : i.status === 'planned' ? '计划中' : '待定';
|
|
return `<div class="card" id="feat-${i.id}">
|
|
<div class="card-h">
|
|
<span>${U.esc(i.title)}</span>
|
|
<div style="display:flex;gap:8px;align-items:center">
|
|
<span style="font-size:11px;color:${statusColor}">● ${statusLabel}</span>
|
|
${Auth.isOwner() ? `<button class="btn btn-o btn-sm" onclick="FeaturesPage.showEdit(${i.id},'${U.escJs(i.title)}','${U.escJs(i.description||'')}','${i.status}')"><i class="fas fa-edit"></i></button>` : ''}
|
|
</div>
|
|
</div>
|
|
<div class="card-b">
|
|
${i.description ? `<p class="tm mb-4">${U.esc(i.description)}</p>` : ''}
|
|
<div style="display:flex;align-items:center;gap:12px">
|
|
<button class="btn btn-${i.my_vote?'s':'o'} btn-sm feat-vote" data-id="${i.id}">
|
|
<i class="fas fa-chevron-up"></i> ${i.votes_count || 0}
|
|
</button>
|
|
<span class="ts tm">${i.my_vote ? '已投票 (点击取消)' : '点击投票'}</span>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
},
|
|
|
|
bindVote(i) {
|
|
const card = document.getElementById('feat-'+i.id);
|
|
if (!card) return;
|
|
card.querySelector('.feat-vote').addEventListener('click', async () => {
|
|
try { await API.post(`/features/${i.id}/vote`); this.load(); } catch (ex) { alert(ex.message); }
|
|
});
|
|
},
|
|
|
|
showCreate() {
|
|
U.modal('添加项目', `
|
|
<form id="feat-form">
|
|
<div class="form-group"><label>标题 *</label><input id="ft-title" required></div>
|
|
<div class="form-group"><label>描述</label><textarea id="ft-desc" rows="2"></textarea></div>
|
|
<div class="modal-f"><button type="button" class="btn btn-o" onclick="App.closeModal()">取消</button><button type="submit" class="btn btn-p">添加</button></div>
|
|
</form>
|
|
`);
|
|
document.getElementById('feat-form').onsubmit = async e => { e.preventDefault();
|
|
try { await API.post('/features', { title: document.getElementById('ft-title').value, description: document.getElementById('ft-desc').value }); App.closeModal(); this.load(); } catch(ex){alert(ex.message);}
|
|
};
|
|
},
|
|
|
|
async showEdit(id, title, desc, status) {
|
|
U.modal('编辑', `
|
|
<form id="fe-edit">
|
|
<div class="form-group"><label>标题</label><input id="fe-title" value="${title}"></div>
|
|
<div class="form-group"><label>描述</label><textarea id="fe-desc" rows="2">${desc}</textarea></div>
|
|
<div class="form-group"><label>状态</label><select id="fe-status">
|
|
<option value="pending" ${status==='pending'?'selected':''}>待定</option>
|
|
<option value="planned" ${status==='planned'?'selected':''}>计划中</option>
|
|
<option value="done" ${status==='done'?'selected':''}>已完成</option>
|
|
</select></div>
|
|
<div class="modal-f"><button type="button" class="btn btn-o" onclick="App.closeModal()">取消</button><button type="button" class="btn btn-d" onclick="FeaturesPage.del(${id})"><i class="fas fa-trash"></i></button><button type="submit" class="btn btn-p">保存</button></div>
|
|
</form>
|
|
`);
|
|
document.getElementById('fe-edit').onsubmit = async e => { e.preventDefault();
|
|
try { await API.put('/features/'+id, { title: document.getElementById('fe-title').value, description: document.getElementById('fe-desc').value, status: document.getElementById('fe-status').value }); App.closeModal(); this.load(); } catch(ex){alert(ex.message);}
|
|
};
|
|
},
|
|
|
|
async del(id) {
|
|
if (!await U.confirm('确认删除?')) return;
|
|
try { await API.req('DELETE', '/features/'+id); App.closeModal(); this.load(); } catch(ex){alert(ex.message);}
|
|
}
|
|
};
|