1132 lines
38 KiB
Plaintext
1132 lines
38 KiB
Plaintext
<%@ 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>
|