GZMachinesWeb/WebContent/WEB-INF/views/login/login.jsp

1132 lines
38 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<title>贵送机具管理系统</title>
<c:set var="bonuspath" value="${pageContext.request.contextPath}" />
<script>
var bonuspath = '${bonuspath}';
</script>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
<title>贵送机具管理系统 - 登录</title>
<%
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
request.getSession().setAttribute("randTxt", uuid);
String sessionId = request.getSession().getId();
response.setHeader("SET-COOKIE", "JSESSIONID="+sessionId+";secure;HttpOnly");
%>
<!-- CSS Resources -->
<link rel="icon" href="${bonuspath}/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="${bonuspath}/favicon.ico" type="image/x-icon" />
<link rel="bookmark" href="${bonuspath}/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="${bonuspath}/static/css/bootstrap/bootstrap1.min.css" />
<link href="${bonuspath}/static/css/sys/images/iconfont/style.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="${bonuspath}/static/css/jquery/jquery-ui.css" />
<link rel="stylesheet" href="${bonuspath}/static/js/layui/css/layui.css" />
<!-- JavaScript Resources -->
<script src="${bonuspath}/static/js/jquery/jquery-3.6.1.js"></script>
<script type="text/javascript" src="${bonuspath}/static/js/jquery/jquery.tips.js"></script>
<script src="${bonuspath}/static/js/jquery/jquery-ui.min.js"></script>
<script src="${bonuspath}/static/js/jquery/jquery.md5.js"></script>
<script src="${bonuspath}/static/js/layui/layui.js"></script>
<script src="${bonuspath}/static/plugins/layer/2.1/layer.js"></script>
<script type="text/javascript" src="${bonuspath}/static/js/sys/login.js"></script>
<script>
// 显示用户协议
function showAgreement() {
layui.use('layer', function(){
var layer = layui.layer;
layer.open({
type: 1,
title: '用户协议',
area: ['90%', '90%'],
maxWidth: '900px',
maxHeight: '700px',
shadeClose: false,
scrollbar: true,
content: $('#agreementContent').html(),
success: function(layero, index){
console.log('弹窗加载成功');
},
error: function(err){
console.error('弹窗加载失败:', err);
}
});
});
}
</script>
<!-- 用户协议内容模板 -->
<script type="text/html" id="agreementContent">
<div style="padding: 20px; height: 500px; overflow-y: auto; background-color: #fff;">
<h3 style="text-align: center; margin-bottom: 20px; color: #333; font-size: 18px;">用户协议</h3>
<p style="text-align: right; color: #666; margin-bottom: 20px;">本协议更新时间【2024】年【12】月【17】日</p>
<div style="color: #333; line-height: 1.6;">
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">一、引言</h4>
<p style="margin-bottom: 10px;">鉴于个人信息和隐私保护的重要性,以及我们对您个人信息和隐私的尊重,我们制定了本《个人信息和隐私保护协议》(以下简称"本协议")。本协议旨在明确我们对您个人信息和隐私的收集、使用、存储、传输和删除等方面的规定,以确保您的个人信息和隐私得到妥善保护。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">二、协议适用说明</h4>
<p style="margin-bottom: 10px;">1. 个人信息:指能够单独或与其他信息结合后识别特定自然人身份的信息,包括但不限于姓名、性别、出生日期、身份证号、联系方式、家庭住址等。</p>
<p style="margin-bottom: 10px;">2. 隐私安全:指个人在特定社会关系中,享有私人生活,不愿公开的个人信息和私人事务。</p>
<p style="margin-bottom: 10px;">3. 适用范围:本协议适用于我们对您个人信息和隐私的保护,包括我们收集、使用、存储、传输和删除您的个人信息和隐私。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">三、信息收集</h4>
<p style="margin-bottom: 10px;">1. 合法性原则:我们将遵循合法性原则,仅在您同意或法律允许的情况下收集您的个人信息和隐私。</p>
<p style="margin-bottom: 10px;">2. 必要性原则:我们将遵循必要性原则,仅收集与实现我们的服务目的直接相关的信息。</p>
<p style="margin-bottom: 10px;">3. 透明性原则:我们将遵循透明性原则,向您公开我们收集的个人信息和隐私的种类、目的和使用方式。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">四、信息使用</h4>
<p style="margin-bottom: 10px;">1. 合法使用:我们将仅在法律允许或您同意的情况下使用您的个人信息和隐私。</p>
<p style="margin-bottom: 10px;">2. 正当使用:我们将遵循正当使用原则,确保使用您的个人信息和隐私是为了实现我们的服务目的,并且不会损害您的合法权益。</p>
<p style="margin-bottom: 10px;">3. 透明使用:我们将遵循透明使用原则,向您公开我们使用您的个人信息和隐私的具体情况。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">五、信息存储与传输</h4>
<p style="margin-bottom: 10px;">1. 安全存储:我们将采取必要的技术和组织措施,确保您的个人信息和隐私得到安全存储。</p>
<p style="margin-bottom: 10px;">2. 加密传输:我们将对您的个人信息和隐私进行加密传输,以确保数据传输过程中的安全性。</p>
<p style="margin-bottom: 10px;">3. 访问控制:我们将严格控制对您的个人信息和隐私的访问权限,确保只有授权人员才能访问相关信息。</p>
<p style="margin-bottom: 10px;">4. 定期审计:为您提供安全保障,个人信息处理者应当定期对其处理个人信息遵守法律、行政法规的情况进行合规审计。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">六、信息删除与注销</h4>
<p style="margin-bottom: 10px;">1. 删除原则:我们将遵循删除原则,确保在达到收集目的后或您要求删除时,及时删除您的个人信息和隐私。</p>
<p style="margin-bottom: 10px;">2. 注销权利:您有权要求我们注销您的个人信息和隐私,我们将在收到您的请求后尽快处理。</p>
<p style="margin-bottom: 10px;">3. 在不幸发生个人信息安全事件后,我们将按照法律法规的要求向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">七、违约责任</h4>
<p style="margin-bottom: 10px;">1. 违反本协议规定的,我们将依法承担相应的法律责任。</p>
<p style="margin-bottom: 10px;">2. 您违反本协议规定的,我们将有权依法追究您的法律责任。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">八、如何保护你的信息</h4>
<p style="margin-bottom: 10px;">(一)我们已采取符合业界标准、合理可行的安全防护措施保护您的信息,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。</p>
<p style="margin-bottom: 10px;">(二)我们有行业先进的以数据为核心,围绕数据生命周期进行的数据安全管理体系,从组织建设、制度设计、人员管理、产品技术等方面多维度提升整个系统的安全性。</p>
<p style="margin-bottom: 10px;">(三)我们会采取合理可行的措施,尽力避免收集无关的个人信息。</p>
<p style="margin-bottom: 10px;">(四)互联网并非绝对安全的环境,使用服务时,我们强烈建议通过安全方式、使用复杂密码,协助我们保证您的账号安全。</p>
<p style="margin-bottom: 10px;">(五)在不幸发生个人信息安全事件后,我们将按照法律法规的要求及时告知您。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">九、我们如何更新本政策</h4>
<p style="margin-bottom: 10px;">1. 为给您提供更好的服务,本应用的产品与服务将不时更新与变化,我们会适时对本协议进行修订。</p>
<p style="margin-bottom: 10px;">2. 本协议更新后,我们会在本应用中发出更新版本,并以弹窗的方式提醒您。</p>
<p style="margin-bottom: 10px;">3. 对于重大变更,我们还会提供更为显著的通知。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">十、我们如何委托处理、共享、转让、公开披露您的个人信息</h4>
<p style="margin-bottom: 10px;">1. 委托处理:为了向您提供更完善、更优质的产品和服务,我们可能会委托合作方处理您的某些个人信息。</p>
<p style="margin-bottom: 10px;">2. 共享:在本应用进行用户注册时,您的账号注册信息会在相关政务服务系统间共享。</p>
<h4 style="color: #333; font-size: 16px; margin: 15px 0;">十一、其他条款</h4>
<p style="margin-bottom: 10px;">1. 本协议自双方签字或盖章之日起生效。</p>
<p style="margin-bottom: 10px;">2. 本协议一式两份,双方各执一份。</p>
<p style="margin-bottom: 10px;">3. 本协议未尽事宜,由双方另行协商确定。如有任何疑问或需要进一步了解,请随时联系我们。</p>
</div>
</div>
</script>
<style>
/* Reset and base styles */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
font-family: "Microsoft YaHei", "微软雅黑", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #333;
overflow-x: hidden;
}
/* 南网蓝色系配色变量 */
:root {
--nangwang-blue: #007aa5;
--nangwang-blue-light: #0089b9;
--nangwang-blue-lighter: #00a0d8;
--nangwang-blue-dark: #006b91;
--nangwang-blue-darker: #005d7e;
--nangwang-blue-gradient: linear-gradient(135deg, #007aa5 0%, #00a0d8 100%);
--nangwang-blue-shadow: rgba(0, 122, 165, 0.3);
--nangwang-blue-shadow-light: rgba(0, 122, 165, 0.1);
}
/* Background and layout */
body {
background: var(--nangwang-blue-gradient);
background-attachment: fixed;
background-size: cover;
position: relative;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('${bonuspath}/static/css/sys/images/login/bg.png') no-repeat center center;
background-size: cover;
opacity: 0.1;
z-index: -1;
}
/* Main container */
.login-container {
width: 100%;
max-width: 420px;
margin: 20px;
perspective: 1000px;
}
.login-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
overflow: hidden;
transform-style: preserve-3d;
transition: all 0.3s ease;
}
.login-card:hover {
transform: translateY(-5px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.15);
}
/* Header section */
.login-header {
background: var(--nangwang-blue-gradient);
padding: 30px 20px;
text-align: center;
position: relative;
overflow: hidden;
}
.login-header::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
animation: rotate 20s linear infinite;
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.logo-container {
position: relative;
z-index: 2;
}
.logo-container img {
max-width: 120px;
height: auto;
filter: brightness(1.2);
transition: transform 0.3s ease;
}
.logo-container img:hover {
transform: scale(1.05);
}
.system-title {
color: white;
font-size: 18px;
font-weight: 500;
margin-top: 10px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
letter-spacing: 1px;
}
/* Form section */
.login-form {
padding: 40px 30px 30px;
background: white;
}
.form-group {
position: relative;
margin-bottom: 25px;
}
.input-container {
position: relative;
display: flex;
align-items: center;
}
.input-icon {
position: absolute;
left: 15px;
font-size: 18px;
color: var(--nangwang-blue);
z-index: 2;
transition: color 0.3s ease;
}
.form-input {
width: 100%;
height: 50px;
padding: 0 15px 0 45px;
border: 2px solid #e1e5e9;
border-radius: 12px;
font-size: 16px;
background: #f8f9fa;
transition: all 0.3s ease;
outline: none;
}
.form-input:focus {
border-color: var(--nangwang-blue);
background: white;
box-shadow: 0 0 0 3px var(--nangwang-blue-shadow-light);
transform: translateY(-1px);
}
.form-input:focus + .input-icon {
color: var(--nangwang-blue-light);
}
.form-input::placeholder {
color: #a0a0a0;
transition: color 0.3s ease;
}
.form-input:focus::placeholder {
color: #c0c0c0;
}
/* Error messages */
.error-message {
position: absolute;
bottom: -20px;
left: 0;
color: #e74c3c;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
}
.error-message.show {
opacity: 1;
}
/* 记住密码选项区域 */
.remember-section {
display: flex;
justify-content: space-between;
align-items: center;
margin: 15px 0 20px;
font-size: 14px;
}
.remember-label {
display: inline-flex;
align-items: center;
cursor: pointer;
color: #666;
transition: color 0.3s ease;
}
.remember-label:hover {
color: #333;
}
.remember-checkbox {
margin-right: 8px;
cursor: pointer;
transform: scale(1.1);
accent-color: var(--nangwang-blue);
}
.forgot-password {
color: var(--nangwang-blue);
text-decoration: none;
font-size: 13px;
transition: all 0.3s ease;
}
.forgot-password:hover {
color: var(--nangwang-blue-light);
text-decoration: underline;
}
/* Agreement section */
.agreement-section {
margin: 20px 0;
text-align: center;
}
.agreement-label {
display: inline-flex;
align-items: center;
cursor: pointer;
font-size: 14px;
color: #666;
transition: color 0.3s ease;
}
.agreement-label:hover {
color: #333;
}
.agreement-checkbox {
margin-right: 8px;
cursor: pointer;
transform: scale(1.1);
accent-color: var(--nangwang-blue);
}
.agreement-link {
color: var(--nangwang-blue);
text-decoration: none;
font-weight: 500;
margin-left: 4px;
border-bottom: 1px solid transparent;
transition: all 0.3s ease;
}
.agreement-link:hover {
border-bottom-color: var(--nangwang-blue);
color: var(--nangwang-blue-light);
}
/* Login button */
.login-button {
width: 100%;
height: 50px;
background: var(--nangwang-blue-gradient);
border: none;
border-radius: 12px;
color: white;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
margin-top: 10px;
}
.login-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s ease;
}
.login-button:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px var(--nangwang-blue-shadow);
background: linear-gradient(135deg, var(--nangwang-blue-light) 0%, var(--nangwang-blue-lighter) 100%);
}
.login-button:hover::before {
left: 100%;
}
.login-button:active {
transform: translateY(0);
}
.login-button:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
/* Responsive design */
@media (max-width: 768px) {
.login-container {
margin: 10px;
max-width: 100%;
}
.login-form {
padding: 30px 20px 20px;
}
.system-title {
font-size: 16px;
}
.form-input {
height: 45px;
font-size: 14px;
}
.login-button {
height: 45px;
font-size: 14px;
}
.remember-section {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
}
@media (max-width: 480px) {
.login-container {
margin: 5px;
}
.login-header {
padding: 20px 15px;
}
.login-form {
padding: 25px 15px 15px;
}
.system-title {
font-size: 14px;
}
}
/* Animation for form elements */
.form-group {
animation: slideInUp 0.6s ease forwards;
opacity: 0;
transform: translateY(30px);
}
.form-group:nth-child(1) { animation-delay: 0.1s; }
.form-group:nth-child(2) { animation-delay: 0.2s; }
.form-group:nth-child(3) { animation-delay: 0.3s; }
.form-group:nth-child(4) { animation-delay: 0.4s; }
.form-group:nth-child(5) { animation-delay: 0.5s; }
@keyframes slideInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
/* Auto-fill styles */
.form-input:-webkit-autofill {
-webkit-box-shadow: 0 0 0 1000px #f8f9fa inset;
-webkit-text-fill-color: #333;
}
.form-input:-webkit-autofill:focus {
-webkit-box-shadow: 0 0 0 1000px white inset;
}
/* Loading state */
.login-button.loading {
pointer-events: none;
}
.login-button.loading::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
margin: auto;
border: 2px solid transparent;
border-top-color: white;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Focus indicators for accessibility */
.form-input:focus,
.login-button:focus,
.agreement-checkbox:focus,
.remember-checkbox:focus,
.agreement-link:focus,
.forgot-password:focus {
outline: 2px solid var(--nangwang-blue);
outline-offset: 2px;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
.login-card {
background: white;
border: 2px solid #333;
}
.form-input {
border-color: #333;
}
.login-button {
background: #333;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Custom checkbox styles for better visual consistency */
.remember-checkbox,
.agreement-checkbox {
width: 18px;
height: 18px;
border-radius: 3px;
position: relative;
}
.remember-checkbox:checked,
.agreement-checkbox:checked {
background-color: var(--nangwang-blue);
border-color: var(--nangwang-blue);
}
/* 安全提示区域 */
.security-tip {
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-left: 4px solid var(--nangwang-blue);
padding: 12px 15px;
margin: 20px 0;
border-radius: 0 8px 8px 0;
font-size: 13px;
color: #666;
}
.security-tip .tip-icon {
color: var(--nangwang-blue);
margin-right: 8px;
font-weight: bold;
}
</style>
</head>
<body>
<div class="login-container">
<div class="login-card">
<!-- Header Section -->
<div class="login-header">
<div class="logo-container">
<img src="${bonuspath}/static/img/loginIcon.png" alt="系统Logo">
<div class="system-title">贵送机具管理系统</div>
</div>
</div>
<!-- Form Section -->
<div class="login-form">
<form action="" method="post" onsubmit="return false" id="loginForm">
<input type="hidden" value="<%=request.getSession().getAttribute("randTxt")%>" name="randSession">
<!-- Username Input -->
<div class="form-group">
<div class="input-container">
<input
class="form-input"
type="text"
id="accountNameId"
name="username"
placeholder="请输入用户名"
required
autocomplete="username"
aria-label="用户名"
/>
<i class="icon-user input-icon" aria-hidden="true"></i>
</div>
<div class="error-message" id="usererror" role="alert"></div>
</div>
<!-- Password Input -->
<div class="form-group">
<div class="input-container">
<input
class="form-input"
type="password"
id="passwordId"
name="password"
placeholder="请输入密码"
required
autocomplete="current-password"
aria-label="密码"
/>
<i class="icon-lock input-icon" aria-hidden="true"></i>
</div>
<div class="error-message" id="passworderror" role="alert"></div>
</div>
<!-- Remember Password and Forgot Password Section -->
<div class="form-group">
<div class="remember-section">
<label class="remember-label">
<input
type="checkbox"
id="rememberCheckbox"
class="remember-checkbox"
aria-label="记住密码"
>
记住密码
</label>
<a style="display: none ;" href="javascript:void(0)" class="forgot-password" onclick="showForgotPassword()"
role="button" aria-label="忘记密码">忘记密码?</a>
</div>
</div>
<!-- Security Tip -->
<div class="form-group" style="display: none">
<div class="security-tip">
<span class="tip-icon">💡</span>
为了您的账户安全,建议在私人设备上使用记住密码功能
</div>
</div>
<!-- Agreement Section -->
<div class="form-group">
<div class="agreement-section">
<label class="agreement-label">
<input
type="checkbox"
id="agreementCheckbox"
class="agreement-checkbox"
required
aria-describedby="agreement-text"
>
<span id="agreement-text">
我已阅读并同意
<a href="javascript:void(0)" onclick="showAgreement()" class="agreement-link"
role="button" aria-label="查看用户协议详情">《用户协议》</a>
</span>
</label>
</div>
</div>
<!-- Login Button -->
<div class="form-group">
<button
type="button"
class="login-button"
id="loginBtn"
aria-label="登录系统"
>
登录
</button>
</div>
</form>
</div>
</div>
</div>
<script>
// Enhanced login functionality with remember password
let isLoginInProgress = false; // 添加登录状态标志
$(document).ready(function() {
// 页面加载时检查是否有保存的用户名
loadRememberedCredentials();
// Input focus effects
$('.form-input').on('focus', function() {
$(this).closest('.form-group').addClass('focused');
}).on('blur', function() {
$(this).closest('.form-group').removeClass('focused');
});
// Real-time validation
$('#accountNameId').on('input', function() {
validateUsername();
});
$('#passwordId').on('input', function() {
validatePassword();
});
// Agreement checkbox validation
$('#agreementCheckbox').on('change', function() {
validateAgreement();
});
// Remember password functionality
$('#rememberCheckbox').on('change', function() {
if (!$(this).is(':checked')) {
// 如果取消勾选,清除保存的信息
clearRememberedCredentials();
}
});
// 重写原有的登录按钮点击事件,添加防重复点击保护
$('#loginBtn').off('click').on('click', function(e) {
e.preventDefault();
if (isLoginInProgress) {
return false;
}
// 清除之前的错误消息
errorclean();
// 检查用户协议
if (!$('#agreementCheckbox').prop('checked')) {
layui.use('layer', function(){
var layer = layui.layer;
layer.msg('请阅读并同意用户协议');
});
return false;
}
// 验证用户名
if($("#accountNameId").val() == '') {
$("#usererror").append("登录名不能为空");
return false;
} else if($("#passwordId").val() == '') {
$("#passworderror").append("密码不能为空");
return false;
} else {
// 设置登录进行中状态
isLoginInProgress = true;
// 保存记住密码的凭据
const username = $('#accountNameId').val().trim();
const password = $('#passwordId').val();
const remember = $('#rememberCheckbox').is(':checked');
if (remember) {
saveCredentials(username, password, true);
}
// 执行原有的登录逻辑
dialogloading();
var loginname = $("#accountNameId").val();
var password = $("#passwordId").val();
loginname = encodeURI(encodeURI(loginname));
password = encodeURI(encodeURI(password));
localStorage.setItem("pwd", $.md5(password));
localStorage.setItem("uname", loginname);
var verifyCode = null;
var code = loginname + ",jy," + $.md5(password) + ",jy," + verifyCode;
$.ajax({
type: 'POST',
url: bonuspath + '/system_login',
data: {
KEYDATA: code,
tm: new Date().getTime(),
uuId: uuid()
},
dataType: 'json',
success: function(data, textStatus) {
dialogloadingClose();
// 重置登录状态(防重复提交保护)
isLoginInProgress = false;
const result = data.result;
if ("success" == result) {
sessionStorage.setItem("token", data.token);
dialogloadingClose();
clearLoginForm();
loginAlert(result);
window.location.href = bonuspath + "/backstage/index";
} else {
clearLoginForm();
loginAlert(result);
const errInfo = " ";
data.result = " ";
}
},
error: function(xhr, status, error) {
dialogloadingClose();
// 重置登录状态(防重复提交保护)
isLoginInProgress = false;
// 处理网络错误
loginAlert("error");
}
});
}
});
// Enter key support - 修复重复触发问题
$('#loginForm').on('keypress', function(e) {
if (e.which === 13) {
e.preventDefault();
if (!isLoginInProgress) {
$('#loginBtn').trigger('click');
}
}
});
// 防止表单默认提交
$('#loginForm').on('submit', function(e) {
e.preventDefault();
return false;
});
});
// 加载记住的凭据
function loadRememberedCredentials() {
try {
const rememberedUsername = localStorage.getItem('rememberedUsername');
const rememberedPassword = localStorage.getItem('rememberedPassword');
const isRemembered = localStorage.getItem('isPasswordRemembered') === 'true';
if (isRemembered && rememberedUsername) {
$('#accountNameId').val(rememberedUsername);
$('#rememberCheckbox').prop('checked', true);
// 只有在有记住的密码时才填充
if (rememberedPassword) {
$('#passwordId').val(atob(rememberedPassword)); // 简单的base64解码
}
// 如果用户名已填充,焦点移动到密码框
if (rememberedUsername && !rememberedPassword) {
$('#passwordId').focus();
}
}
} catch (error) {
console.log('加载记住的凭据时出错:', error);
}
}
// 保存凭据
function saveCredentials(username, password, remember) {
try {
if (remember) {
localStorage.setItem('rememberedUsername', username);
localStorage.setItem('rememberedPassword', btoa(password)); // 简单的base64编码
localStorage.setItem('isPasswordRemembered', 'true');
} else {
clearRememberedCredentials();
}
} catch (error) {
console.log('保存凭据时出错:', error);
}
}
// 清除记住的凭据
function clearRememberedCredentials() {
try {
localStorage.removeItem('rememberedUsername');
localStorage.removeItem('rememberedPassword');
localStorage.removeItem('isPasswordRemembered');
} catch (error) {
console.log('清除凭据时出错:', error);
}
}
function validateUsername() {
const username = $('#accountNameId').val().trim();
const errorElement = $('#usererror');
if (username.length === 0) {
showError(errorElement, '请输入用户名');
return false;
} else if (username.length < 2) {
showError(errorElement, '用户名至少需要2个字符');
return false;
} else {
hideError(errorElement);
return true;
}
}
function validatePassword() {
const password = $('#passwordId').val();
const errorElement = $('#passworderror');
if (password.length === 0) {
showError(errorElement, '请输入密码');
return false;
} else if (password.length < 6) {
showError(errorElement, '密码至少需要6个字符');
return false;
} else {
hideError(errorElement);
return true;
}
}
function validateAgreement() {
const isChecked = $('#agreementCheckbox').is(':checked');
if (!isChecked) {
layui.use('layer', function(){
var layer = layui.layer;
layer.msg('请先阅读并同意用户协议', {icon: 5});
});
return false;
}
return true;
}
function validateForm() {
const isUsernameValid = validateUsername();
const isPasswordValid = validatePassword();
const isAgreementValid = validateAgreement();
return isUsernameValid && isPasswordValid && isAgreementValid;
}
function showError(element, message) {
element.text(message).addClass('show');
element.closest('.form-group').addClass('error');
}
function hideError(element) {
element.removeClass('show');
element.closest('.form-group').removeClass('error');
}
// 清除所有错误消息
function hideAllErrors() {
$('.error-message').removeClass('show');
$('.form-group').removeClass('error');
}
// 添加原有登录逻辑中需要的工具函数
function uuid() {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 32; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23];
var uuid = s.join("");
return uuid;
}
function errorclean() {
$("#usererror").empty();
$("#passworderror").empty();
}
function clearLoginForm() {
$("#verifyCodeId").val("");
$("#passwordId").val("");
}
function loginAlert(msg) {
if("codeerror" == msg){
$("#verifyCodeId").tips({side : 3,msg : "验证码不正确!",bg : '#FF2D2D',time : 2});
$("#verifyCodeId").focus();
} else if("nullup" == msg){
$("#accountNameId").tips({side : 3,msg : "用户名或密码不能为空!",bg : '#FF2D2D',time : 2});
$("#accountNameId").focus();
} else if("nullcode" == msg){
$("#verifyCodeId").tips({side : 3,msg : "验证码不能为空!",bg : '#FF2D2D',time : 2});
$("#verifyCodeId").focus();
} else if("usererror" == msg){
$("#accountNameId").tips({side : 3,msg : "用户名或密码有误!",bg : '#FF2D2D',time : 2});
$("#accountNameId").focus();
} else if("attemptserror" == msg){
dialogerror("错误次数过多!");
} else if("error" == msg){
dialogerror("输入有误!");
} else if("inactive" == msg){
dialogerror("未激活!");
}
}
function dialogerror(Str) {
layui.use('layer', function(){
var layer = layui.layer;
layer.msg(Str, {icon: 5, time: 3000});
});
}
function dialogloading() {
layui.use('layer', function(){
var layer = layui.layer;
layer.load(1, {
shade: [0.1,'#fff']
});
});
}
function dialogloadingClose() {
layui.use('layer', function(){
var layer = layui.layer;
layer.closeAll('loading');
});
}
// 忘记密码功能
function showForgotPassword() {
layui.use('layer', function(){
var layer = layui.layer;
layer.prompt({
title: '忘记密码',
formType: 0,
value: $('#accountNameId').val(),
area: ['300px', '150px']
}, function(value, index){
if (value.trim() === '') {
layer.msg('请输入用户名', {icon: 5});
return false;
}
// 这里应该调用重置密码的接口
layer.msg('密码重置链接已发送到您的邮箱', {icon: 1, time: 3000});
layer.close(index);
});
});
}
// 增强的键盘导航
$(document).on('keydown', function(e) {
// Tab键在表单元素间导航
if (e.key === 'Tab') {
const focusableElements = $('#loginForm').find('input, button, a').filter(':visible');
const currentIndex = focusableElements.index(document.activeElement);
if (e.shiftKey) {
// Shift + Tab (向上)
if (currentIndex === 0) {
focusableElements.last().focus();
e.preventDefault();
}
} else {
// Tab (向下)
if (currentIndex === focusableElements.length - 1) {
focusableElements.first().focus();
e.preventDefault();
}
}
}
});
</script>
</body>
</html>