fix: polish authentication and responsive controls
This commit is contained in:
@@ -6,15 +6,17 @@
|
||||
第 <span class="font-bold text-textMain">{{ pagination.page }}</span> / {{ pagination.pages }} 页
|
||||
</div>
|
||||
{% if pagination.pages > 1 %}
|
||||
<div class="flex flex-nowrap items-center gap-2 overflow-x-auto pb-1">
|
||||
<div class="flex w-full min-w-0 flex-nowrap items-center gap-2 overflow-x-auto pb-1 sm:w-auto">
|
||||
{% set prev_page = pagination.prev_num if pagination.has_prev else pagination.page %}
|
||||
<a
|
||||
class="ui-btn ui-btn-sm ui-btn-secondary {{ 'pointer-events-none opacity-50' if not pagination.has_prev }}"
|
||||
href="{{ url_for(endpoint, page=prev_page) }}"
|
||||
aria-disabled="{{ 'false' if pagination.has_prev else 'true' }}"
|
||||
aria-label="上一页"
|
||||
title="上一页"
|
||||
>
|
||||
<span class="material-symbols-outlined text-lg">chevron_left</span>
|
||||
上一页
|
||||
<span class="hidden sm:inline">上一页</span>
|
||||
</a>
|
||||
<div class="flex items-center gap-1">
|
||||
{% for page in pagination.iter_pages(left_edge=1, left_current=1, right_current=2, right_edge=1) %}
|
||||
@@ -34,8 +36,10 @@
|
||||
class="ui-btn ui-btn-sm ui-btn-secondary {{ 'pointer-events-none opacity-50' if not pagination.has_next }}"
|
||||
href="{{ url_for(endpoint, page=next_page) }}"
|
||||
aria-disabled="{{ 'false' if pagination.has_next else 'true' }}"
|
||||
aria-label="下一页"
|
||||
title="下一页"
|
||||
>
|
||||
下一页
|
||||
<span class="hidden sm:inline">下一页</span>
|
||||
<span class="material-symbols-outlined text-lg">chevron_right</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "base.html" %}
|
||||
{% extends "auth_base.html" %}
|
||||
{% block title %}接受注册邀请{% endblock %}
|
||||
{% block content %}
|
||||
<section class="mx-auto max-w-md rounded-xl border border-line bg-white p-5 shadow-panel sm:p-6">
|
||||
|
||||
+23
-21
@@ -10,28 +10,30 @@
|
||||
<p class="mt-2 text-sm text-textSub">管理用户账号、注册状态和预测记录。</p>
|
||||
</div>
|
||||
|
||||
<section class="mt-6 rounded-xl border border-line bg-white p-5 shadow-panel">
|
||||
<h2 class="font-extrabold">用户注册</h2>
|
||||
<form method="post" action="{{ url_for('main.update_registration_setting') }}" class="mt-3 flex items-center gap-3">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<label class="text-sm">
|
||||
<input type="checkbox" name="allow_registration" {{ 'checked' if registration_allowed }}>
|
||||
允许自助注册
|
||||
</label>
|
||||
<button class="ui-btn ui-btn-sm ui-btn-primary">保存</button>
|
||||
</form>
|
||||
</section>
|
||||
<div class="mt-6 grid gap-6 xl:grid-cols-2">
|
||||
<section class="rounded-xl border border-line bg-white p-5 shadow-panel">
|
||||
<h2 class="font-extrabold">用户注册</h2>
|
||||
<form method="post" action="{{ url_for('main.update_registration_setting') }}" class="mt-3 flex items-center gap-3">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<label class="text-sm">
|
||||
<input type="checkbox" name="allow_registration" {{ 'checked' if registration_allowed }}>
|
||||
允许自助注册
|
||||
</label>
|
||||
<button class="ui-btn ui-btn-sm ui-btn-primary">保存</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="mt-6 rounded-xl border border-line bg-white p-5 shadow-panel">
|
||||
<h2 class="font-extrabold">邀请注册</h2>
|
||||
<p class="mt-1 text-sm text-textSub">即使关闭自助注册,也可向指定邮箱发送一次性注册链接。</p>
|
||||
<form method="post" action="{{ url_for('main.admin_send_registration_invitation') }}" class="mt-4 flex flex-col gap-2 sm:flex-row" novalidate>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<label class="sr-only" for="inviteEmail">受邀邮箱</label>
|
||||
<input id="inviteEmail" name="email" type="email" required autocomplete="email" class="min-w-0 flex-1 rounded-lg border border-line px-3 py-2 text-sm" placeholder="受邀人的邮箱地址">
|
||||
<button class="ui-btn ui-btn-sm ui-btn-primary shrink-0">发送注册链接</button>
|
||||
</form>
|
||||
</section>
|
||||
<section class="rounded-xl border border-line bg-white p-5 shadow-panel">
|
||||
<h2 class="font-extrabold">邀请注册</h2>
|
||||
<p class="mt-1 text-sm text-textSub">即使关闭自助注册,也可向指定邮箱发送一次性注册链接。</p>
|
||||
<form method="post" action="{{ url_for('main.admin_send_registration_invitation') }}" class="mt-4 flex flex-col gap-2 sm:flex-row sm:items-center" novalidate>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<label class="sr-only" for="inviteEmail">受邀邮箱</label>
|
||||
<input id="inviteEmail" name="email" type="email" required autocomplete="email" class="min-w-0 w-full rounded-lg border border-line px-3 py-2 text-sm sm:w-80" placeholder="受邀人的邮箱地址">
|
||||
<button class="ui-btn ui-btn-sm ui-btn-primary shrink-0">发送注册链接</button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="mt-6 rounded-xl border border-line bg-white p-5 shadow-panel">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}账户验证{% endblock %} | 供水管道健康评估系统</title>
|
||||
<meta name="theme-color" content="#005EB8">
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.svg') }}" type="image/svg+xml">
|
||||
<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-4 py-5 sm:px-5">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -143,6 +143,16 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-[11px] tracking-[0.18em] uppercase text-slate-500 mb-2">确认密码</label>
|
||||
<div class="relative">
|
||||
<span class="material-symbols-outlined absolute left-4 top-1/2 -translate-y-1/2 text-slate-400 text-lg">lock</span>
|
||||
<input id="registerPasswordConfirm" name="password_confirm" type="password" minlength="12" required data-field-label="确认密码" autocomplete="new-password" {{ 'disabled' if not allow_registration }} class="w-full pl-11 pr-12 py-3.5 rounded-xl bg-[#eceff3] border border-transparent focus:border-primary focus:ring-0 disabled:cursor-not-allowed disabled:bg-slate-100 disabled:text-slate-400" placeholder="请再次输入密码" />
|
||||
<button class="password-toggle" type="button" data-password-toggle="registerPasswordConfirm" aria-label="显示确认密码" aria-pressed="false" tabindex="-1" {{ 'disabled' if not allow_registration }}>
|
||||
<span class="material-symbols-outlined" aria-hidden="true">visibility</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-[11px] tracking-[0.18em] uppercase text-slate-500 mb-2">图形验证码</label>
|
||||
<div class="grid grid-cols-[1fr_92px_44px] gap-3 items-center">
|
||||
@@ -327,6 +337,16 @@
|
||||
showAppNotification(`密码至少需要 ${minLength} 位`, 'error', undefined, shortPassword);
|
||||
markFieldError(shortPassword);
|
||||
shortPassword.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
const password = form.querySelector('[name="password"]');
|
||||
const confirmation = form.querySelector('[name="password_confirm"]');
|
||||
if (password && confirmation && password.value !== confirmation.value) {
|
||||
event.preventDefault();
|
||||
showAppNotification('两次密码输入不一致', 'error', undefined, confirmation);
|
||||
markFieldError(confirmation);
|
||||
confirmation.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "base.html" %}
|
||||
{% extends "auth_base.html" %}
|
||||
{% block title %}重置密码{% endblock %}
|
||||
{% block content %}
|
||||
<section class="mx-auto max-w-md rounded-xl border border-line bg-white p-5 shadow-panel sm:p-6">
|
||||
|
||||
Reference in New Issue
Block a user