121 lines
4.8 KiB
HTML
121 lines
4.8 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>{{ title }} | 供水管道健康评估系统</title>
|
|
<link href="{{ url_for('static', filename='css/app.css') }}" rel="stylesheet">
|
|
</head>
|
|
<body class="min-h-screen bg-page text-textMain">
|
|
<main class="mx-auto flex min-h-screen max-w-md items-center px-5">
|
|
<section class="w-full rounded-2xl border border-line bg-white p-7 shadow-panel">
|
|
<span class="material-symbols-outlined text-4xl text-primary">mark_email_read</span>
|
|
<h1 class="mt-3 text-2xl font-extrabold">{{ title }}</h1>
|
|
<p class="mt-2 text-sm leading-6 text-textSub">验证码已发送至 {{ email }},10 分钟内有效。</p>
|
|
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% for category, message in messages %}
|
|
<p class="mt-4 rounded-lg bg-dangerSoft p-3 text-sm text-dangerText">{{ message }}</p>
|
|
{% endfor %}
|
|
{% endwith %}
|
|
|
|
<form method="post" class="mt-7" id="verificationForm">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<input id="verificationCode" type="hidden" name="code" value="">
|
|
<fieldset>
|
|
<legend class="text-sm font-semibold">请输入 6 位验证码</legend>
|
|
<div class="mt-3 grid grid-cols-6 gap-2" id="codeInputs">
|
|
{% for index in range(6) %}
|
|
<input
|
|
type="text"
|
|
inputmode="numeric"
|
|
autocomplete="one-time-code"
|
|
maxlength="1"
|
|
aria-label="验证码第 {{ index + 1 }} 位"
|
|
class="h-12 min-w-0 rounded-lg border border-line text-center text-xl font-bold tracking-wide focus:border-primary focus:ring-primary"
|
|
data-code-digit
|
|
{% if index == 0 %}autofocus{% endif %}
|
|
>
|
|
{% endfor %}
|
|
</div>
|
|
</fieldset>
|
|
<button id="verifyButton" class="ui-btn ui-btn-primary mt-6 w-full" type="submit">验证并继续</button>
|
|
</form>
|
|
|
|
<form method="post" action="{{ url_for('main.resend_code', purpose=purpose) }}" class="mt-4 text-center">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button id="resendButton" class="text-sm font-semibold text-primary disabled:cursor-not-allowed disabled:text-slate-400" type="submit" disabled>
|
|
<span id="resendText">{{ resend_seconds }} 秒后可重新发送</span>
|
|
</button>
|
|
</form>
|
|
</section>
|
|
</main>
|
|
<script>
|
|
(() => {
|
|
const inputs = Array.from(document.querySelectorAll('[data-code-digit]'));
|
|
const hiddenCode = document.getElementById('verificationCode');
|
|
const form = document.getElementById('verificationForm');
|
|
const resendButton = document.getElementById('resendButton');
|
|
const resendText = document.getElementById('resendText');
|
|
let remainingSeconds = {{ resend_seconds|int }};
|
|
|
|
function updateCode() {
|
|
hiddenCode.value = inputs.map((input) => input.value).join('');
|
|
}
|
|
|
|
function fillDigits(value, startIndex = 0) {
|
|
const digits = value.replace(/\D/g, '').slice(0, inputs.length - startIndex);
|
|
for (let index = 0; index < digits.length; index += 1) {
|
|
inputs[startIndex + index].value = digits[index];
|
|
}
|
|
updateCode();
|
|
const nextIndex = Math.min(startIndex + digits.length, inputs.length - 1);
|
|
inputs[nextIndex].focus();
|
|
}
|
|
|
|
inputs.forEach((input, index) => {
|
|
input.addEventListener('input', () => {
|
|
if (input.value.length > 1) {
|
|
fillDigits(input.value, index);
|
|
return;
|
|
}
|
|
input.value = input.value.replace(/\D/g, '');
|
|
updateCode();
|
|
if (input.value && index < inputs.length - 1) inputs[index + 1].focus();
|
|
});
|
|
|
|
input.addEventListener('keydown', (event) => {
|
|
if (event.key === 'Backspace' && !input.value && index > 0) {
|
|
inputs[index - 1].focus();
|
|
}
|
|
});
|
|
|
|
input.addEventListener('paste', (event) => {
|
|
event.preventDefault();
|
|
fillDigits(event.clipboardData.getData('text'), index);
|
|
});
|
|
});
|
|
|
|
form.addEventListener('submit', (event) => {
|
|
updateCode();
|
|
if (hiddenCode.value.length !== inputs.length) {
|
|
event.preventDefault();
|
|
inputs.find((input) => !input.value)?.focus();
|
|
}
|
|
});
|
|
|
|
const timer = window.setInterval(() => {
|
|
remainingSeconds -= 1;
|
|
if (remainingSeconds <= 0) {
|
|
window.clearInterval(timer);
|
|
resendButton.disabled = false;
|
|
resendText.textContent = '重新发送验证码';
|
|
return;
|
|
}
|
|
resendText.textContent = `${remainingSeconds} 秒后可重新发送`;
|
|
}, 1000);
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|