2024-09-10 10:55:19 +08:00
|
|
|
|
<html lang="zh">
|
|
|
|
|
<head>
|
|
|
|
|
<title>晚餐吃什么鸭</title>
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
2024-09-10 15:39:26 +08:00
|
|
|
|
<link rel="stylesheet" href="/static/bootstrap.min.css">
|
2024-09-10 10:55:19 +08:00
|
|
|
|
</head>
|
|
|
|
|
<body>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
<div class="container text-center pt-5">
|
2024-09-10 10:55:19 +08:00
|
|
|
|
<p>每天8:00-17:30间开放匿名投票更新,17:30以后允许发起抽签,抽签结果确定后不可更改</p>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
<p>第一名与第二名得票数相差不超过10%时随机抽签,按其得票数决定中签概率,否则选择第一名</p>
|
2024-09-12 18:00:26 +08:00
|
|
|
|
<p>投票结果仅供参考,最终解释权归部门总经理、副总经理所有</p>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
{% for last_result in last_results %}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<p>今日{{ last_result.value }}最终得票数降低{{ 2 + loop.index0 }}0%</p>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
{% endfor %}
|
2024-09-13 08:28:41 +08:00
|
|
|
|
<form id="inputForm" class="form-inline" onsubmit="return false;">
|
2024-09-10 10:55:19 +08:00
|
|
|
|
<div class="form-group">
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<div class="mb-3">
|
|
|
|
|
<div class="input-group">
|
|
|
|
|
<label class="input-group-text" for="inputName" id="basic-addon1">姓名</label>
|
2024-09-14 08:29:16 +08:00
|
|
|
|
<input type="text" class="form-control" {{ 'readonly="readonly"' if user_menu.nickname else '' | safe }}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
id="inputName" name="nickname" value="{{ user_menu.nickname }}">
|
|
|
|
|
</div>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
</div>
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<div class="mb-3">
|
2024-09-14 17:34:37 +08:00
|
|
|
|
<label class="input-group-addon">我选择</label>
|
2024-09-10 10:55:19 +08:00
|
|
|
|
</div>
|
|
|
|
|
{% for choice in all_choice %}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<div class="mb-3 row">
|
|
|
|
|
<div class="col-9">
|
|
|
|
|
<div class="input-group">
|
|
|
|
|
<label for="range{{ loop.index }}" class="form-label">
|
|
|
|
|
<span>{{ choice.label }} - </span>
|
|
|
|
|
<span class="percentage">{{ '{:.2f}'.format((user_menu.menu.get(choice.name) or 0) * 100) }}</span>%
|
|
|
|
|
</label>
|
2024-09-14 17:34:37 +08:00
|
|
|
|
<input type="range" class="form-range" data-skip-falsy="true"
|
|
|
|
|
id="range{{ loop.index }}" name="choice[{{ choice.name }}]:number"
|
2024-09-14 07:58:21 +08:00
|
|
|
|
min="0" max="10" step="1"
|
|
|
|
|
value="{{ (user_menu.menu.get(choice.name) or 0) * 10 }}">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-3">
|
|
|
|
|
<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>
|
2024-09-10 10:55:19 +08:00
|
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<button type="button" class="btn btn-primary" onclick="update()">更新</button>
|
|
|
|
|
<button type="button" class="btn btn-secondary" onclick="clearValue()">不吃</button>
|
2024-09-11 10:15:20 +08:00
|
|
|
|
<button type="button" id="btnRoll"
|
2024-09-14 07:58:21 +08:00
|
|
|
|
class="btn btn-secondary" {{ "" if can_roll == True else ' disabled="disabled"' | safe }}
|
2024-09-10 10:55:19 +08:00
|
|
|
|
onclick="roll()">开始抽签
|
|
|
|
|
</button>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
<div class="pt-3">
|
2024-09-14 17:34:37 +08:00
|
|
|
|
<label>大家的选择 - 总投票人数:{{ total_vote }}</label>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
<ul class="list-group pt-2 mb-4">
|
2024-09-11 15:51:44 +08:00
|
|
|
|
{% for key in summary_keys %}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<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">{{ '{:.2f}'.format(summary[key] | round(2)) }}票</span>
|
|
|
|
|
<span class="col-3">{{ '{:.2f}'.format(summary[key] / total_vote * 100 | round(2)) }}%</span>
|
2024-09-10 10:55:19 +08:00
|
|
|
|
</li>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
{% if (users|length) > 3 %}
|
|
|
|
|
<div class="pt-1 mb-3">
|
2024-09-13 08:28:41 +08:00
|
|
|
|
<label class="mb-2">参与投票人员</label>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
<ul class="list-group list-group-horizontal">
|
|
|
|
|
{% for user in users %}
|
|
|
|
|
<li class="list-group-item">{{ user }}</li>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
2024-09-14 17:34:37 +08:00
|
|
|
|
{% if ((users|length) > 3 or result) %}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<div class="pt-1 mb-3">
|
2024-09-14 17:34:37 +08:00
|
|
|
|
<label class="mb-2">{{ ('如果吃' + predict_result) if predict_result else '' }}就餐人员</label>
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<ul class="list-group list-group-horizontal">
|
|
|
|
|
{% for user in eat_users %}
|
|
|
|
|
<li class="list-group-item">{{ user }}</li>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
2024-09-13 08:28:41 +08:00
|
|
|
|
<div class="pt-1 mb-3">
|
|
|
|
|
<label class="mb-2">最近点餐结果</label>
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<ul class="list-group">
|
2024-09-13 08:28:41 +08:00
|
|
|
|
{% for recent_result in recent_results %}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
|
<span>{{ recent_result.value }}</span>
|
|
|
|
|
<span>{{ recent_result.datestr }}</span>
|
|
|
|
|
</li>
|
2024-09-13 08:28:41 +08:00
|
|
|
|
{% endfor %}
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
2024-09-12 10:24:38 +08:00
|
|
|
|
<footer class="footer mt-auto py-3 bg-light">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col-12">
|
|
|
|
|
<a class="link-secondary link-offset-2"
|
|
|
|
|
href="https://git.zaneyork.cn:8443/ZaneYork/dinner_vote">本项目抽签完全公开透明,源码开放欢迎随时审查</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col-12">
|
|
|
|
|
<span style="font-size: 0.7rem">Copyright © <script>document.write(new Date().getFullYear().toString())</script> Zane York. All Rights Reserved.</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</footer>
|
2024-09-10 10:55:19 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
2024-09-10 15:39:26 +08:00
|
|
|
|
<script src="/static/jquery-3.2.1.min.js"></script>
|
|
|
|
|
<script src="/static/jquery.serializejson.js"></script>
|
|
|
|
|
<script src="/static/bootstrap.bundle.min.js"></script>
|
2024-09-10 10:55:19 +08:00
|
|
|
|
|
2024-09-11 15:51:44 +08:00
|
|
|
|
<!--suppress JSUnresolvedReference -->
|
2024-09-10 10:55:19 +08:00
|
|
|
|
<script>
|
2024-09-12 18:00:26 +08:00
|
|
|
|
document.addEventListener('keydown', function (event) {
|
|
|
|
|
if (event.key === 'Enter' || event.keyCode === 13) {
|
|
|
|
|
update();
|
2024-09-13 08:28:41 +08:00
|
|
|
|
return false;
|
2024-09-12 18:00:26 +08:00
|
|
|
|
}
|
|
|
|
|
});
|
2024-09-14 07:58:21 +08:00
|
|
|
|
const rangesInput = $("input[type=range]");
|
|
|
|
|
const checkBoxs = $("input[type=checkbox]")
|
|
|
|
|
rangesInput.change(function () {
|
|
|
|
|
const values = rangesInput.map(function () {
|
2024-09-11 15:51:44 +08:00
|
|
|
|
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++) {
|
2024-09-12 10:24:38 +08:00
|
|
|
|
spans[i].innerHTML = summary > 0 ? (parseFloat(values[i]) * 100 / summary).toFixed(2) : 0;
|
2024-09-14 07:58:21 +08:00
|
|
|
|
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);
|
|
|
|
|
}
|
2024-09-11 15:51:44 +08:00
|
|
|
|
}
|
2024-09-14 07:58:21 +08:00
|
|
|
|
$(rangesInput[0]).trigger('change');
|
2024-09-11 15:51:44 +08:00
|
|
|
|
});
|
|
|
|
|
|
2024-09-10 10:55:19 +08:00
|
|
|
|
function update() {
|
2024-09-11 15:51:44 +08:00
|
|
|
|
const data = $('#inputForm').serializeJSON();
|
2024-09-12 10:24:38 +08:00
|
|
|
|
const nickname = data.nickname;
|
|
|
|
|
data.nickname = undefined;
|
2024-09-10 10:55:19 +08:00
|
|
|
|
$.ajax({
|
2024-09-12 10:24:38 +08:00
|
|
|
|
url: 'dinner/update?nickname=' + nickname + '&value=' + JSON.stringify(data),
|
2024-09-10 10:55:19 +08:00
|
|
|
|
dataType: 'json',
|
|
|
|
|
success: function (result) {
|
2024-09-10 15:39:26 +08:00
|
|
|
|
if (result.code === 0) {
|
2024-09-10 10:55:19 +08:00
|
|
|
|
window.location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('更新失败: ' + result.data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearValue() {
|
2024-09-14 07:58:21 +08:00
|
|
|
|
const data = $('#inputForm').serializeJSON();
|
|
|
|
|
const nickname = data.nickname;
|
2024-09-10 10:55:19 +08:00
|
|
|
|
$.ajax({
|
2024-09-14 07:58:21 +08:00
|
|
|
|
url: 'dinner/update?nickname=' + nickname + '&value=',
|
2024-09-10 10:55:19 +08:00
|
|
|
|
dataType: 'json',
|
|
|
|
|
success: function (result) {
|
2024-09-10 15:39:26 +08:00
|
|
|
|
if (result.code === 0) {
|
2024-09-10 10:55:19 +08:00
|
|
|
|
window.location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('更新失败: ' + result.data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function roll() {
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: 'dinner/roll',
|
|
|
|
|
dataType: 'json',
|
|
|
|
|
success: function (result) {
|
2024-09-10 15:39:26 +08:00
|
|
|
|
if (result.code === 0) {
|
2024-09-10 10:55:19 +08:00
|
|
|
|
window.location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('更新失败: ' + result.data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2024-09-11 10:15:20 +08:00
|
|
|
|
|
|
|
|
|
$(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;
|
2024-09-11 15:51:44 +08:00
|
|
|
|
const btn = $("#btnRoll");
|
2024-09-11 10:15:20 +08:00
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-09-10 10:55:19 +08:00
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|