440 lines
11 KiB
HTML
440 lines
11 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}注册新用户{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="register-container">
|
||
<div class="register-card">
|
||
<div class="register-header">
|
||
<h1>注册新用户</h1>
|
||
<p>创建新的系统用户账户</p>
|
||
</div>
|
||
|
||
<form method="POST" class="register-form">
|
||
<div class="form-group">
|
||
<label for="username">
|
||
<i class="fas fa-user"></i>
|
||
用户名
|
||
</label>
|
||
<input type="text"
|
||
id="username"
|
||
name="username"
|
||
required
|
||
minlength="3"
|
||
maxlength="20"
|
||
placeholder="请输入用户名(3-20个字符)">
|
||
<small class="form-text">用户名长度为3-20个字符,只能包含字母、数字和下划线</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="password">
|
||
<i class="fas fa-lock"></i>
|
||
密码
|
||
</label>
|
||
<input type="password"
|
||
id="password"
|
||
name="password"
|
||
required
|
||
minlength="6"
|
||
placeholder="请输入密码(至少6位)">
|
||
<small class="form-text">密码长度至少6位,建议包含字母和数字</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="confirm_password">
|
||
<i class="fas fa-lock"></i>
|
||
确认密码
|
||
</label>
|
||
<input type="password"
|
||
id="confirm_password"
|
||
name="confirm_password"
|
||
required
|
||
minlength="6"
|
||
placeholder="请再次输入密码">
|
||
<small class="form-text">请再次输入相同的密码进行确认</small>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="permission">
|
||
<i class="fas fa-user-cog"></i>
|
||
权限级别
|
||
</label>
|
||
<select id="permission" name="permission" required>
|
||
<option value="">请选择权限级别</option>
|
||
<option value="1">普通用户 - 可以录入和查询数据</option>
|
||
<option value="0">管理员 - 拥有所有权限</option>
|
||
</select>
|
||
<small class="form-text">
|
||
<strong>普通用户:</strong>可以上传图片、录入数据、查询数据<br>
|
||
<strong>管理员:</strong>拥有所有权限,包括用户管理和数据管理
|
||
</small>
|
||
</div>
|
||
|
||
<div class="form-actions">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="fas fa-user-plus"></i>
|
||
创建用户
|
||
</button>
|
||
<a href="{{ url_for('user_management') }}" class="btn btn-secondary">
|
||
<i class="fas fa-arrow-left"></i>
|
||
返回用户管理
|
||
</a>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.register-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
min-height: calc(100vh - 200px);
|
||
padding: 20px;
|
||
}
|
||
|
||
.register-card {
|
||
background: white;
|
||
border-radius: 12px;
|
||
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
|
||
padding: 40px;
|
||
width: 100%;
|
||
max-width: 500px;
|
||
}
|
||
|
||
.register-header {
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.register-header h1 {
|
||
color: #333;
|
||
margin-bottom: 10px;
|
||
font-size: 28px;
|
||
}
|
||
|
||
.register-header p {
|
||
color: #666;
|
||
font-size: 16px;
|
||
margin: 0;
|
||
}
|
||
|
||
.register-form {
|
||
width: 100%;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.form-group label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.form-group label i {
|
||
margin-right: 8px;
|
||
color: #007bff;
|
||
width: 16px;
|
||
}
|
||
|
||
.form-group input,
|
||
.form-group select {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
border: 2px solid #e0e0e0;
|
||
border-radius: 8px;
|
||
font-size: 14px;
|
||
transition: all 0.3s ease;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.form-group input:focus,
|
||
.form-group select:focus {
|
||
outline: none;
|
||
border-color: #007bff;
|
||
box-shadow: 0 0 0 3px rgba(0,123,255,0.1);
|
||
}
|
||
|
||
.form-group input:invalid {
|
||
border-color: #dc3545;
|
||
}
|
||
|
||
.form-group input:valid {
|
||
border-color: #28a745;
|
||
}
|
||
|
||
.form-text {
|
||
display: block;
|
||
margin-top: 5px;
|
||
font-size: 12px;
|
||
color: #666;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.form-actions {
|
||
display: flex;
|
||
gap: 15px;
|
||
margin-top: 30px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 12px 24px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
text-decoration: none;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
transition: all 0.3s ease;
|
||
flex: 1;
|
||
}
|
||
|
||
.btn i {
|
||
margin-right: 8px;
|
||
}
|
||
|
||
.btn-primary {
|
||
background-color: #007bff;
|
||
color: white;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background-color: #0056b3;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(0,123,255,0.3);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background-color: #6c757d;
|
||
color: white;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background-color: #545b62;
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(108,117,125,0.3);
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.register-container {
|
||
padding: 10px;
|
||
}
|
||
|
||
.register-card {
|
||
padding: 30px 20px;
|
||
}
|
||
|
||
.form-actions {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.btn {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
/* 密码强度指示器 */
|
||
.password-strength {
|
||
margin-top: 5px;
|
||
height: 4px;
|
||
background-color: #e0e0e0;
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.password-strength-bar {
|
||
height: 100%;
|
||
width: 0%;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.strength-weak {
|
||
background-color: #dc3545;
|
||
width: 33%;
|
||
}
|
||
|
||
.strength-medium {
|
||
background-color: #ffc107;
|
||
width: 66%;
|
||
}
|
||
|
||
.strength-strong {
|
||
background-color: #28a745;
|
||
width: 100%;
|
||
}
|
||
|
||
/* 表单验证样式 */
|
||
.form-group.error input,
|
||
.form-group.error select {
|
||
border-color: #dc3545;
|
||
box-shadow: 0 0 0 3px rgba(220,53,69,0.1);
|
||
}
|
||
|
||
.form-group.success input,
|
||
.form-group.success select {
|
||
border-color: #28a745;
|
||
box-shadow: 0 0 0 3px rgba(40,167,69,0.1);
|
||
}
|
||
|
||
.error-message {
|
||
color: #dc3545;
|
||
font-size: 12px;
|
||
margin-top: 5px;
|
||
display: none;
|
||
}
|
||
|
||
.success-message {
|
||
color: #28a745;
|
||
font-size: 12px;
|
||
margin-top: 5px;
|
||
display: none;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
// 表单验证
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const form = document.querySelector('.register-form');
|
||
const username = document.getElementById('username');
|
||
const password = document.getElementById('password');
|
||
const confirmPassword = document.getElementById('confirm_password');
|
||
const permission = document.getElementById('permission');
|
||
|
||
// 用户名验证
|
||
username.addEventListener('input', function() {
|
||
const value = this.value;
|
||
const formGroup = this.closest('.form-group');
|
||
|
||
if (value.length < 3) {
|
||
setFieldError(formGroup, '用户名至少需要3个字符');
|
||
} else if (value.length > 20) {
|
||
setFieldError(formGroup, '用户名不能超过20个字符');
|
||
} else if (!/^[a-zA-Z0-9_]+$/.test(value)) {
|
||
setFieldError(formGroup, '用户名只能包含字母、数字和下划线');
|
||
} else {
|
||
setFieldSuccess(formGroup, '用户名格式正确');
|
||
}
|
||
});
|
||
|
||
// 密码验证
|
||
password.addEventListener('input', function() {
|
||
const value = this.value;
|
||
const formGroup = this.closest('.form-group');
|
||
|
||
if (value.length < 6) {
|
||
setFieldError(formGroup, '密码至少需要6个字符');
|
||
} else {
|
||
setFieldSuccess(formGroup, '密码长度符合要求');
|
||
}
|
||
|
||
// 检查确认密码
|
||
if (confirmPassword.value) {
|
||
validateConfirmPassword();
|
||
}
|
||
});
|
||
|
||
// 确认密码验证
|
||
confirmPassword.addEventListener('input', validateConfirmPassword);
|
||
|
||
function validateConfirmPassword() {
|
||
const formGroup = confirmPassword.closest('.form-group');
|
||
|
||
if (confirmPassword.value !== password.value) {
|
||
setFieldError(formGroup, '两次输入的密码不一致');
|
||
} else if (confirmPassword.value.length >= 6) {
|
||
setFieldSuccess(formGroup, '密码确认正确');
|
||
}
|
||
}
|
||
|
||
// 权限选择验证
|
||
permission.addEventListener('change', function() {
|
||
const formGroup = this.closest('.form-group');
|
||
|
||
if (this.value === '') {
|
||
setFieldError(formGroup, '请选择权限级别');
|
||
} else {
|
||
setFieldSuccess(formGroup, '权限级别已选择');
|
||
}
|
||
});
|
||
|
||
// 表单提交验证
|
||
form.addEventListener('submit', function(e) {
|
||
let isValid = true;
|
||
|
||
// 验证用户名
|
||
if (username.value.length < 3 || username.value.length > 20 || !/^[a-zA-Z0-9_]+$/.test(username.value)) {
|
||
isValid = false;
|
||
setFieldError(username.closest('.form-group'), '用户名格式不正确');
|
||
}
|
||
|
||
// 验证密码
|
||
if (password.value.length < 6) {
|
||
isValid = false;
|
||
setFieldError(password.closest('.form-group'), '密码长度至少6位');
|
||
}
|
||
|
||
// 验证确认密码
|
||
if (password.value !== confirmPassword.value) {
|
||
isValid = false;
|
||
setFieldError(confirmPassword.closest('.form-group'), '两次输入的密码不一致');
|
||
}
|
||
|
||
// 验证权限选择
|
||
if (permission.value === '') {
|
||
isValid = false;
|
||
setFieldError(permission.closest('.form-group'), '请选择权限级别');
|
||
}
|
||
|
||
if (!isValid) {
|
||
e.preventDefault();
|
||
}
|
||
});
|
||
|
||
function setFieldError(formGroup, message) {
|
||
formGroup.classList.remove('success');
|
||
formGroup.classList.add('error');
|
||
|
||
let errorMsg = formGroup.querySelector('.error-message');
|
||
if (!errorMsg) {
|
||
errorMsg = document.createElement('div');
|
||
errorMsg.className = 'error-message';
|
||
formGroup.appendChild(errorMsg);
|
||
}
|
||
errorMsg.textContent = message;
|
||
errorMsg.style.display = 'block';
|
||
|
||
const successMsg = formGroup.querySelector('.success-message');
|
||
if (successMsg) {
|
||
successMsg.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
function setFieldSuccess(formGroup, message) {
|
||
formGroup.classList.remove('error');
|
||
formGroup.classList.add('success');
|
||
|
||
let successMsg = formGroup.querySelector('.success-message');
|
||
if (!successMsg) {
|
||
successMsg = document.createElement('div');
|
||
successMsg.className = 'success-message';
|
||
formGroup.appendChild(successMsg);
|
||
}
|
||
successMsg.textContent = message;
|
||
successMsg.style.display = 'block';
|
||
|
||
const errorMsg = formGroup.querySelector('.error-message');
|
||
if (errorMsg) {
|
||
errorMsg.style.display = 'none';
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %} |