Files
MC_Report/public/js/pages/polls.js

82 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const PollsPage = {
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="PollsPage.showCreate()"><i class="fas fa-plus"></i> 创建投票</button>'
: '';
await this.load();
},
async load() {
const ct = document.getElementById('page-content');
try {
const polls = await API.get('/polls/active');
ct.innerHTML = polls.length === 0
? '<div class="empty"><i class="fas fa-poll"></i><p>暂无进行中的投票</p></div>'
: polls.map(p => this.renderPoll(p)).join('');
for (const p of polls) this.bindVote(p);
} catch (e) { ct.innerHTML = `<div class="alert alert-e">${e.message}</div>`; }
},
renderPoll(p) {
const opts = p.options || [];
const max = Math.max(1, ...Object.values(p.votes || {}));
return `<div class="card" id="poll-${p.id}">
<div class="card-h"><span>${U.esc(p.title)}</span><span class="ts tm">${p.total||0} 票</span></div>
<div class="card-b">
${p.description?`<p class="tm mb-4">${U.esc(p.description)}</p>`:''}
<div style="display:flex;flex-direction:column;gap:8px">
${opts.map((o,i) => {
const v = p.votes?.[i] || 0;
const pct = p.total ? Math.round(v/p.total*100) : 0;
const my = p.my_vote === i;
return `<div class="poll-opt" style="position:relative;overflow:hidden;border:1px solid var(--g200);border-radius:var(--r);cursor:pointer" data-poll="${p.id}" data-idx="${i}">
<div style="position:absolute;top:0;left:0;bottom:0;width:${pct}%;background:${my?'var(--pl)':'var(--g2)'};transition:width .3s;z-index:0"></div>
<div style="position:relative;z-index:1;display:flex;justify-content:space-between;align-items:center;padding:10px 14px;font-size:13px">
<span>${my?'<i class="fas fa-check" style="color:var(--p)"></i> ':''}${U.esc(o)}</span>
<span class="fb">${v}${pct}%</span>
</div>
</div>`;
}).join('')}
</div>
</div>
</div>`;
},
bindVote(p) {
const card = document.getElementById('poll-'+p.id);
if (!card) return;
card.querySelectorAll('.poll-opt').forEach(el => {
el.addEventListener('click', async () => {
try {
await API.post(`/polls/${p.id}/vote`, { option_index: parseInt(el.dataset.idx) });
this.load();
} catch (ex) { alert(ex.message); }
});
});
},
showCreate() {
U.modal('创建投票', `
<form id="poll-form">
<div class="form-group"><label>标题 *</label><input id="pl-title" required></div>
<div class="form-group"><label>描述</label><textarea id="pl-desc" rows="2"></textarea></div>
<div class="form-group"><label>选项 (每行一个至少2个) *</label><textarea id="pl-opts" rows="4" placeholder="选项A&#10;选项B&#10;选项C" required></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('poll-form').onsubmit = async e => {
e.preventDefault();
const opts = document.getElementById('pl-opts').value.split('\n').map(s=>s.trim()).filter(s=>s);
if (opts.length < 2) return alert('至少需要2个选项');
try {
await API.post('/polls', { title: document.getElementById('pl-title').value, description: document.getElementById('pl-desc').value, options: opts });
App.closeModal();
this.load();
} catch (ex) { alert(ex.message); }
};
}
};