feat: 结算台改为用户名密码登录
This commit is contained in:
@@ -490,6 +490,216 @@
|
||||
color: #ff6b6b;
|
||||
}
|
||||
.fail-counter.show { display: flex; }
|
||||
|
||||
/* ===== 登录方式切换 Tab ===== */
|
||||
.login-tabs {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.login-tabs__item {
|
||||
position: relative;
|
||||
padding: 10px 18px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.login-tabs__item:hover { color: rgba(255, 255, 255, 0.7); }
|
||||
.login-tabs__item::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
right: 12px;
|
||||
bottom: -1px;
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
border-radius: 1px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.login-tabs__item.active {
|
||||
color: #4a90d9;
|
||||
}
|
||||
.login-tabs__item.active::after {
|
||||
background: #4a90d9;
|
||||
box-shadow: 0 0 8px rgba(74, 144, 217, 0.5);
|
||||
}
|
||||
|
||||
/* 人脸面板容器(撑满左列) */
|
||||
.face-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
min-height: 0;
|
||||
}
|
||||
/* 账号面板:整体垂直水平居中,不撑满 */
|
||||
.account-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 18px;
|
||||
min-height: 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
/* hidden 属性兜底:避免被 display:flex 覆盖 */
|
||||
.face-panel[hidden],
|
||||
.account-panel[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* ===== 账号密码登录表单 ===== */
|
||||
.account-form {
|
||||
width: 340px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
background: rgba(26, 43, 74, 0.35);
|
||||
border: 1px solid rgba(74, 144, 217, 0.18);
|
||||
border-radius: 14px;
|
||||
padding: 32px 32px 26px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.account-form__header {
|
||||
text-align: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.account-form__title {
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.account-form__sub {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
margin-top: 6px;
|
||||
}
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.form-field__label {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.form-field__input-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.form-field__icon {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
font-size: 15px;
|
||||
opacity: 0.65;
|
||||
pointer-events: none;
|
||||
}
|
||||
.form-field__input {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
padding: 0 12px 0 38px;
|
||||
background: rgba(5, 10, 26, 0.55);
|
||||
border: 1px solid rgba(74, 144, 217, 0.2);
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s;
|
||||
outline: none;
|
||||
}
|
||||
.form-field__input::placeholder {
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
.form-field__input:focus {
|
||||
border-color: #4a90d9;
|
||||
background: rgba(5, 10, 26, 0.8);
|
||||
box-shadow: 0 0 0 3px rgba(74, 144, 217, 0.15);
|
||||
}
|
||||
.login-submit {
|
||||
margin-top: 4px;
|
||||
height: 44px;
|
||||
background: linear-gradient(135deg, #4a90d9 0%, #2563eb 100%);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: all 0.2s;
|
||||
box-shadow: 0 4px 14px rgba(74, 144, 217, 0.3);
|
||||
}
|
||||
.login-submit:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 6px 20px rgba(74, 144, 217, 0.45);
|
||||
}
|
||||
.login-submit:active { transform: translateY(0); }
|
||||
.login-submit:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
.login-submit__icon { font-size: 15px; }
|
||||
.login-hint {
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
/* 账号面板底部提示(与表单同宽对齐) */
|
||||
.account-tips {
|
||||
width: 340px;
|
||||
background: rgba(26, 43, 74, 0.4);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: 10px;
|
||||
padding: 12px 16px 14px;
|
||||
}
|
||||
.account-tips__title {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
font-weight: 500;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.account-tips__list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
.account-tips__list li {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
padding-left: 14px;
|
||||
position: relative;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.account-tips__list li::before {
|
||||
content: "·";
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
color: #4a90d9;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -506,13 +716,16 @@
|
||||
<!-- 主内容 -->
|
||||
<div class="main-area">
|
||||
|
||||
<!-- 左列:人脸识别区 -->
|
||||
<!-- 左列:登录区(人脸/账号密码切换) -->
|
||||
<div class="camera-col">
|
||||
<div class="col-label">
|
||||
<span class="col-label__bar"></span>
|
||||
人脸识别登录
|
||||
<!-- 登录方式切换 Tab -->
|
||||
<div class="login-tabs" role="tablist">
|
||||
<button class="login-tabs__item" data-tab="account" role="tab" aria-selected="true">账号密码登录</button>
|
||||
<button class="login-tabs__item" data-tab="face" role="tab" aria-selected="false">人脸识别登录</button>
|
||||
</div>
|
||||
|
||||
<!-- 视图 A:人脸识别面板 -->
|
||||
<div class="face-panel" id="facePanel" hidden>
|
||||
<div class="camera-frame" id="cameraFrame">
|
||||
<div class="camera-frame__bg"></div>
|
||||
<div class="camera-frame__cross-h"></div>
|
||||
@@ -555,6 +768,50 @@
|
||||
<div class="fail-counter" id="failCounter">
|
||||
⚠️ 识别失败,今日剩余尝试次数:<span id="failCount">3</span> 次
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 视图 B:账号密码登录面板 -->
|
||||
<div class="account-panel" id="accountPanel">
|
||||
<div class="account-form">
|
||||
<div class="account-form__header">
|
||||
<div class="account-form__title">收银员登录</div>
|
||||
<div class="account-form__sub">请输入工号和密码进入结算系统</div>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label class="form-field__label">工号</label>
|
||||
<div class="form-field__input-wrap">
|
||||
<span class="form-field__icon">👤</span>
|
||||
<input type="text" class="form-field__input" id="loginAccount" placeholder="请输入工号,如 CS001" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label class="form-field__label">密码</label>
|
||||
<div class="form-field__input-wrap">
|
||||
<span class="form-field__icon">🔒</span>
|
||||
<input type="password" class="form-field__input" id="loginPassword" placeholder="请输入登录密码">
|
||||
</div>
|
||||
</div>
|
||||
<button class="login-submit" id="loginSubmit" type="button">
|
||||
<span class="login-submit__icon">🔑</span>
|
||||
登 录
|
||||
</button>
|
||||
<div class="login-hint">
|
||||
<span>📞 忘记密码请联系食堂管理员</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="account-tips">
|
||||
<div class="account-tips__title">
|
||||
<span class="col-label__bar"></span>
|
||||
登录提示
|
||||
</div>
|
||||
<ul class="account-tips__list">
|
||||
<li>请使用食堂统一分配的工号登录</li>
|
||||
<li>连续 5 次密码错误将锁定账号 30 分钟</li>
|
||||
<li>登录遇到问题可点击右侧「故障报修」</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右列:班次信息 + 操作入口 -->
|
||||
@@ -698,33 +955,117 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 登录方式切换 ==================== */
|
||||
var tabs = document.querySelectorAll('.login-tabs__item');
|
||||
var facePanel = document.getElementById('facePanel');
|
||||
var accountPanel = document.getElementById('accountPanel');
|
||||
var loginSubmit = document.getElementById('loginSubmit');
|
||||
var loginAccount = document.getElementById('loginAccount');
|
||||
var loginPassword = document.getElementById('loginPassword');
|
||||
/* 当前激活的登录方式:account / face */
|
||||
var activeTab = 'account';
|
||||
|
||||
function switchTab(tabName) {
|
||||
if (tabName === activeTab) return;
|
||||
activeTab = tabName;
|
||||
|
||||
tabs.forEach(function(tab) {
|
||||
var isActive = tab.dataset.tab === tabName;
|
||||
tab.classList.toggle('active', isActive);
|
||||
tab.setAttribute('aria-selected', isActive ? 'true' : 'false');
|
||||
});
|
||||
|
||||
if (tabName === 'account') {
|
||||
facePanel.hidden = true;
|
||||
accountPanel.hidden = false;
|
||||
stopRecognition();
|
||||
} else {
|
||||
accountPanel.hidden = true;
|
||||
facePanel.hidden = false;
|
||||
startRecognition();
|
||||
}
|
||||
}
|
||||
|
||||
tabs.forEach(function(tab) {
|
||||
tab.addEventListener('click', function() {
|
||||
switchTab(tab.dataset.tab);
|
||||
});
|
||||
});
|
||||
|
||||
/* 账号密码登录提交 */
|
||||
loginSubmit.addEventListener('click', function() {
|
||||
var account = loginAccount.value.trim();
|
||||
var password = loginPassword.value;
|
||||
if (!account) {
|
||||
showToast('请输入工号', 'warn');
|
||||
loginAccount.focus();
|
||||
return;
|
||||
}
|
||||
if (!password) {
|
||||
showToast('请输入密码', 'warn');
|
||||
loginPassword.focus();
|
||||
return;
|
||||
}
|
||||
/* 模拟登录成功 */
|
||||
loginSubmit.disabled = true;
|
||||
loginSubmit.innerHTML = '<span class="login-submit__icon">⏳</span> 登录中...';
|
||||
setTimeout(function() {
|
||||
showToast('登录成功,正在进入系统...', 'success');
|
||||
setTimeout(function() {
|
||||
window.location.href = '02-standby.html';
|
||||
}, 800);
|
||||
}, 600);
|
||||
});
|
||||
|
||||
/* 回车键提交 */
|
||||
loginPassword.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') loginSubmit.click();
|
||||
});
|
||||
loginAccount.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') loginPassword.focus();
|
||||
});
|
||||
|
||||
/* ==================== 人脸识别流程模拟 ==================== */
|
||||
var frame = document.getElementById('cameraFrame');
|
||||
var statusText = document.getElementById('statusText');
|
||||
var failCounter = document.getElementById('failCounter');
|
||||
var failCountEl = document.getElementById('failCount');
|
||||
var failCount = 3;
|
||||
/* 保存人脸流程的所有定时器,便于切换 Tab 时清除 */
|
||||
var faceTimers = [];
|
||||
|
||||
function clearFaceTimers() {
|
||||
faceTimers.forEach(function(t) { clearTimeout(t); });
|
||||
faceTimers = [];
|
||||
}
|
||||
|
||||
function stopRecognition() {
|
||||
clearFaceTimers();
|
||||
frame.className = 'camera-frame';
|
||||
statusText.textContent = '请面向摄像头进行识别';
|
||||
}
|
||||
|
||||
function startRecognition() {
|
||||
clearFaceTimers();
|
||||
/* 阶段 1:提示用户 */
|
||||
frame.className = 'camera-frame';
|
||||
statusText.textContent = '请面向摄像头进行识别';
|
||||
|
||||
/* 阶段 2:1.5s 后开始扫描 */
|
||||
setTimeout(function() {
|
||||
faceTimers.push(setTimeout(function() {
|
||||
frame.classList.add('scanning');
|
||||
statusText.textContent = '人脸识别中...';
|
||||
}, 1500);
|
||||
}, 1500));
|
||||
|
||||
/* 阶段 3:4s 后识别成功,1.5s 后跳转待机页 */
|
||||
setTimeout(function() {
|
||||
faceTimers.push(setTimeout(function() {
|
||||
frame.classList.remove('scanning');
|
||||
frame.classList.add('success');
|
||||
statusText.textContent = '识别成功';
|
||||
setTimeout(function() {
|
||||
faceTimers.push(setTimeout(function() {
|
||||
window.location.href = '02-standby.html';
|
||||
}, 1500);
|
||||
}, 4000);
|
||||
}, 1500));
|
||||
}, 4000));
|
||||
}
|
||||
|
||||
/* ==================== Toast ==================== */
|
||||
@@ -743,8 +1084,14 @@
|
||||
updateClock();
|
||||
detectMealType();
|
||||
setInterval(updateClock, 1000);
|
||||
/* 自动启动人脸识别模拟 */
|
||||
setTimeout(startRecognition, 800);
|
||||
/* 默认激活「账号密码登录」Tab:HTML 初始即显示账号面板,人脸面板 hidden */
|
||||
tabs.forEach(function(tab) {
|
||||
tab.classList.toggle('active', tab.dataset.tab === 'account');
|
||||
});
|
||||
accountPanel.hidden = false;
|
||||
facePanel.hidden = true;
|
||||
/* 聚焦工号输入框,方便快速登录 */
|
||||
setTimeout(function() { loginAccount.focus(); }, 200);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user