dinner_vote/templates/dinner.html

272 lines
14 KiB
HTML
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.

{% extends "base.html" %}
{% block title %}晚餐吃什么鸭{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
<div class="border rounded p-2 mb-2 text-start" style="text-indent: 2em">
<div class="m-1">每天8:00-17:30间开放匿名投票更新17:30以后允许发起抽签抽签结果确定后不可更改。</div>
<div class="m-1">第一名与第二名得票数相差不超过<strong>10%</strong>时随机抽签,按其得票数决定中签概率,否则选择第一名。
</div>
<div class="m-1">投票结果仅供参考,最终解释权归部门总经理、副总经理所有。</div>
</div>
<div class="alert alert-light text-start" role="alert" style="text-indent: 2em">
{% for last_result in last_results %}
<div class="m-1">
今日<strong>{{ last_result.value }}</strong>最终得票数降低<strong>{{ 2 + loop.index0 }}0%</strong></div>
{% endfor %}
</div>
<form id="inputForm" class="form-inline" onsubmit="return false;">
<div class="form-group">
<div class="accordion">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseMyChoice" aria-expanded="true"
aria-controls="collapseMyChoice">
我选择
</button>
</h2>
<div id="collapseMyChoice" class="accordion-collapse collapse show">
<div class="accordion-body">
<div class="mb-3">
<div class="input-group">
<label class="input-group-text" for="inputName" id="basic-addon1">姓名</label>
<input type="text"
class="form-control" {{ 'readonly="readonly"' if user_menu.nickname else '' | safe }}
id="inputName" name="nickname" value="{{ user_menu.nickname }}">
</div>
</div>
<div class="mb-3 row p-2">
{% for choice in all_choice %}
<div class="col-6 mb-1 p-1 border rounded {{ loop.cycle("rounded-end-0", "border-start-0 rounded-start-0") }}">
<div class="row">
<label for="range{{ loop.index }}"
class="col-12 d-flex justify-content-between align-items-center">
<span>{{ choice.label }}</span>
<span class="percentage">{{ '{:.1f}'.format((user_menu.menu.get(choice.name) or 0) * 100) }}%</span>
</label>
</div>
<div class="d-flex justify-content-between">
<div class="col-sm-8 col-md-9 col-lg-10">
<input type="range" class="form-range" data-skip-falsy="true"
id="range{{ loop.index }}"
name="choice[{{ choice.name }}]:number"
min="0" max="10" step="1"
value="{{ (user_menu.menu.get(choice.name) or 0) * 10 }}">
</div>
<div class="col-auto">
<input class="form-check-input" type="checkbox" name="dislike[]"
id="checkDislike{{ loop.index }}" value="{{ choice.name }}"
{{ 'checked' if choice.name in user_menu.dislike else '' }}>
<label class="form-check-label" for="checkDislike{{ loop.index }}">
不吃
</label>
</div>
</div>
</div>
{% endfor %}
</div>
<button type="button" class="btn btn-outline-primary" onclick="update()">更新</button>
<button type="button" class="btn btn-outline-secondary" onclick="clearValue()">不吃</button>
<button type="button" id="btnRoll"
class="btn btn-outline-secondary" {{ "" if can_roll == True else ' disabled="disabled"' | safe }}
onclick="roll()">开始抽签
</button>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseAllChoice" aria-expanded="true"
aria-controls="collapseAllChoice">
大家的选择
</button>
</h2>
<div id="collapseAllChoice" class="accordion-collapse collapse show">
<div class="accordion-body">
<label class="d-flex justify-content-between">
总投票人数:{{ total_vote }}
</label>
<ul class="list-group pt-2 mb-4">
{% for key in summary_keys %}
<li class="list-group-item d-flex justify-content-between align-items-center{{ " active" if result == key else "" }} {{ " list-group-item-primary" if predict_result == key else "" }}">
<span class="col-5">{{ key }}</span>
<span class="col-3">{{ '{:.1f}'.format(summary[key] | round(1)) }}票</span>
<span class="col-3">{{ '{:.1f}'.format(summary[key] / total_vote * 100 | round(1)) }}%</span>
</li>
{% else %}
<li class="list-group-item">
<span>大家还没有选择</span>
</li>
{% endfor %}
</ul>
{% if (users|length) > 3 %}
<div class="pt-1 mb-3">
<label class="mb-2">参与投票人员</label>
<ul class="list-group list-group-horizontal">
{% for user in users %}
<li class="list-group-item">{{ user }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if ((users|length) > 3 or result) %}
<div class="pt-1 mb-3">
<label class="mb-2">{{ ('如果吃' + predict_result) if predict_result else '' }}就餐人员</label>
<ul class="list-group list-group-horizontal">
{% for user in eat_users %}
<li class="list-group-item">{{ user }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseRecentResult" aria-expanded="false"
aria-controls="collapseRecentResult">
最近点餐结果
</button>
</h2>
<div id="collapseRecentResult" class="accordion-collapse collapse">
<div class="accordion-body">
<div class="pt-1 mb-3">
<ul class="list-group">
{% for recent_result in recent_results %}
<li onclick="viewChart('{{ recent_result.datestr }}')"
class="list-group-item d-flex justify-content-between align-items-center">
<span>{{ recent_result.value }}</span>
<span>{{ recent_result.datestr }}</span>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
{% endblock %}
{% block script %}
{{ super() }}
<!--suppress JSUnresolvedReference -->
<script>
document.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.keyCode === 13) {
update();
return false;
}
});
const rangesInput = $("input[type=range]");
const checkBoxs = $("input[type=checkbox]")
rangesInput.change(function () {
const values = rangesInput.map(function () {
return $(this).val();
}).get();
const summary = values.reduce((a, b) => parseInt(a) + parseInt(b));
const spans = $(".percentage")
for (let i = 0; i < values.length; i++) {
spans[i].innerHTML = (summary > 0 ? (parseFloat(values[i]) * 100 / summary).toFixed(1) : '0.0') + '%';
if (values[i] > 0 && checkBoxs[i].checked) {
checkBoxs[i].checked = false;
}
}
});
checkBoxs.change(function () {
const data = $('#inputForm').serializeJSON();
const values = checkBoxs.map(function () {
return $(this).val();
}).get();
for (let i = 0; i < values.length; i++) {
if (data.dislike.includes(values[i])) {
$(rangesInput[i]).val(0);
}
}
$(rangesInput[0]).trigger('change');
});
function update() {
const data = $('#inputForm').serializeJSON();
const nickname = data.nickname;
data.nickname = undefined;
$.ajax({
url: 'dinner/update?nickname=' + nickname + '&value=' + JSON.stringify(data),
dataType: 'json',
success: function (result) {
if (result.code === 0) {
window.location.reload();
} else {
alert('更新失败: ' + result.data)
}
}
})
}
function clearValue() {
const data = $('#inputForm').serializeJSON();
const nickname = data.nickname;
$.ajax({
url: 'dinner/update?nickname=' + nickname + '&value=',
dataType: 'json',
success: function (result) {
if (result.code === 0) {
window.location.reload();
} else {
alert('更新失败: ' + result.data)
}
}
})
}
function roll() {
$.ajax({
url: 'dinner/roll',
dataType: 'json',
success: function (result) {
if (result.code === 0) {
window.location.reload();
} else {
alert('更新失败: ' + result.data)
}
}
})
}
function viewChart(datestr) {
window.location.href = 'chart?date=' + datestr;
}
$(function () {
const counterId = window.setInterval(counter, 1000);
function counter() {
const now = new Date();
const targetTime = new Date(
now.getFullYear(), now.getMonth(), now.getDate(),
17, 30, 0, 0
);
const diff = targetTime - now;
const btn = $("#btnRoll");
if (diff <= 0) {
window.clearInterval(counterId);
btn.text('开始抽签');
btn.attr('disabled', null)
return;
}
// Convert diff to hours, minutes, and seconds
const hours = Math.floor(diff / (1000 * 60 * 60)).toString().padStart(2, '0');
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)).toString().padStart(2, '0');
const seconds = Math.floor((diff % (1000 * 60)) / 1000).toString().padStart(2, '0');
btn.text(hours + ':' + minutes + ':' + seconds)
}
});
</script>
{% endblock %}