2025-06-20 17:47:53 +08:00
|
|
|
|
<%@ 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>
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="zh-CN">
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<head>
|
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
|
|
|
|
|
|
<title>贵送机具管理系统 - 登录</title>
|
2025-06-20 17:47:53 +08:00
|
|
|
|
|
|
|
|
|
|
<%
|
|
|
|
|
|
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
|
|
|
|
|
|
request.getSession().setAttribute("randTxt", uuid);
|
|
|
|
|
|
String sessionId = request.getSession().getId();
|
|
|
|
|
|
response.setHeader("SET-COOKIE", "JSESSIONID="+sessionId+";secure;HttpOnly");
|
|
|
|
|
|
%>
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<!-- CSS Resources -->
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<link rel="icon" href="${bonuspath}/favicon.ico" type="image/x-icon" />
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<link rel="shortcut icon" href="${bonuspath}/favicon.ico" type="image/x-icon" />
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<link rel="bookmark" href="${bonuspath}/favicon.ico" type="image/x-icon" />
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<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>
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<script src="${bonuspath}/static/js/jquery/jquery-ui.min.js"></script>
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<script src="${bonuspath}/static/js/jquery/jquery.md5.js"></script>
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<script src="${bonuspath}/static/js/layui/layui.js"></script>
|
|
|
|
|
|
<script src="${bonuspath}/static/plugins/layer/2.1/layer.js"></script>
|
2025-07-10 18:01:14 +08:00
|
|
|
|
<script type="text/javascript" src="${bonuspath}/static/js/sys/login.js"></script>
|
|
|
|
|
|
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<script>
|
|
|
|
|
|
// 显示用户协议
|
|
|
|
|
|
function showAgreement() {
|
|
|
|
|
|
layui.use('layer', function(){
|
|
|
|
|
|
var layer = layui.layer;
|
|
|
|
|
|
layer.open({
|
|
|
|
|
|
type: 1,
|
|
|
|
|
|
title: '用户协议',
|
2025-07-10 18:01:14 +08:00
|
|
|
|
area: ['90%', '90%'],
|
|
|
|
|
|
maxWidth: '900px',
|
|
|
|
|
|
maxHeight: '700px',
|
2025-06-20 17:47:53 +08:00
|
|
|
|
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>
|
2025-07-10 18:01:14 +08:00
|
|
|
|
|
2025-06-20 17:47:53 +08:00
|
|
|
|
<style>
|
2025-07-10 18:01:14 +08:00
|
|
|
|
/* Reset and base styles */
|
|
|
|
|
|
* {
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 0;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
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 */
|
2025-06-20 17:47:53 +08:00
|
|
|
|
body {
|
2025-07-10 18:01:14 +08:00
|
|
|
|
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;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-group {
|
2025-07-10 18:01:14 +08:00
|
|
|
|
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;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
/* Agreement section */
|
|
|
|
|
|
.agreement-section {
|
|
|
|
|
|
margin: 20px 0;
|
|
|
|
|
|
text-align: center;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.agreement-label {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
transition: color 0.3s ease;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.agreement-label:hover {
|
|
|
|
|
|
color: #333;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.agreement-checkbox {
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
|
accent-color: var(--nangwang-blue);
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.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;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.agreement-link:hover {
|
|
|
|
|
|
border-bottom-color: var(--nangwang-blue);
|
|
|
|
|
|
color: var(--nangwang-blue-light);
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
/* 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;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.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;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.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%);
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.login-button:hover::before {
|
|
|
|
|
|
left: 100%;
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.login-button:active {
|
|
|
|
|
|
transform: translateY(0);
|
2025-06-20 17:47:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
.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;
|
|
|
|
|
|
}
|
2025-06-20 17:47:53 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
2025-07-10 18:01:14 +08:00
|
|
|
|
|
|
|
|
|
|
<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
|
2025-07-15 18:16:08 +08:00
|
|
|
|
let isLoginInProgress = false; // 添加登录状态标志
|
|
|
|
|
|
|
2025-07-10 18:01:14 +08:00
|
|
|
|
$(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();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-07-15 18:16:08 +08:00
|
|
|
|
// 重写原有的登录按钮点击事件,添加防重复点击保护
|
|
|
|
|
|
$('#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");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-07-10 18:01:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-07-15 18:16:08 +08:00
|
|
|
|
// Enter key support - 修复重复触发问题
|
2025-07-10 18:01:14 +08:00
|
|
|
|
$('#loginForm').on('keypress', function(e) {
|
|
|
|
|
|
if (e.which === 13) {
|
2025-07-15 18:16:08 +08:00
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
if (!isLoginInProgress) {
|
|
|
|
|
|
$('#loginBtn').trigger('click');
|
|
|
|
|
|
}
|
2025-07-10 18:01:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-07-15 18:16:08 +08:00
|
|
|
|
|
|
|
|
|
|
// 防止表单默认提交
|
|
|
|
|
|
$('#loginForm').on('submit', function(e) {
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
2025-07-10 18:01:14 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 加载记住的凭据
|
|
|
|
|
|
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');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-15 18:16:08 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清除所有错误消息
|
|
|
|
|
|
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']
|
2025-07-10 18:01:14 +08:00
|
|
|
|
});
|
2025-07-15 18:16:08 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function dialogloadingClose() {
|
|
|
|
|
|
layui.use('layer', function(){
|
|
|
|
|
|
var layer = layui.layer;
|
|
|
|
|
|
layer.closeAll('loading');
|
|
|
|
|
|
});
|
2025-07-10 18:01:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 忘记密码功能
|
|
|
|
|
|
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>
|
2025-06-20 17:47:53 +08:00
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|