用户系统
This commit is contained in:
		
							
								
								
									
										440
									
								
								templates/register.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										440
									
								
								templates/register.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,440 @@
 | 
			
		||||
{% 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 %}
 | 
			
		||||
		Reference in New Issue
	
	Block a user