feat: 称重打包页新增秤重显示、操作列、下一步弹窗流程,全局精简文案
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
2465e051dd
commit
801a75d7f3
@@ -0,0 +1,288 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1280, initial-scale=1.0">
|
||||
<title>净菜配比秤 - 登录 | 蚁熊智能餐养平台</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
|
||||
background: #05080f; color: #fff;
|
||||
min-height: 100vh; min-width: 1280px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* PAD 设备外壳 */
|
||||
.device-frame {
|
||||
width: 1280px; height: 720px;
|
||||
background: #0e1326;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex; flex-direction: column;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.top-bar {
|
||||
display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px;
|
||||
}
|
||||
.top-bar__title {
|
||||
flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85);
|
||||
}
|
||||
|
||||
/* 主内容:登录面板居中 */
|
||||
.login-main {
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
height: calc(100% - 44px); padding: 24px 32px;
|
||||
}
|
||||
|
||||
/* 登录面板 */
|
||||
.login-panel {
|
||||
width: 480px; display: flex; flex-direction: column; gap: 20px;
|
||||
background: #1a2b4a; border-radius: 16px; padding: 32px 40px;
|
||||
}
|
||||
.login-panel__title {
|
||||
font-size: 18px; font-weight: 600; color: rgba(255,255,255,0.85); text-align: center;
|
||||
}
|
||||
.login-panel__subtitle {
|
||||
font-size: 12px; color: rgba(255,255,255,0.4); text-align: center; margin-top: -12px;
|
||||
}
|
||||
|
||||
/* 登录方式切换 Tab */
|
||||
.login-tabs {
|
||||
display: flex; gap: 0; border-bottom: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
.login-tab {
|
||||
flex: 1; padding: 12px; text-align: center; font-size: 13px; color: rgba(255,255,255,0.5);
|
||||
cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s;
|
||||
}
|
||||
.login-tab:hover { color: rgba(255,255,255,0.8); }
|
||||
.login-tab.active {
|
||||
color: #4a90d9; border-bottom-color: #4a90d9;
|
||||
}
|
||||
|
||||
/* 人脸识别区 */
|
||||
.face-section {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 24px 0;
|
||||
}
|
||||
.face-section.hidden { display: none; }
|
||||
.face-frame {
|
||||
width: 200px; height: 200px; border-radius: 50%;
|
||||
border: 3px dashed rgba(74,144,217,0.4);
|
||||
display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 8px;
|
||||
background: rgba(26,43,74,0.3); cursor: pointer; transition: all 0.3s;
|
||||
}
|
||||
.face-frame:hover {
|
||||
border-color: #4a90d9; background: rgba(74,144,217,0.1);
|
||||
}
|
||||
.face-frame__icon { font-size: 44px; color: rgba(255,255,255,0.3); }
|
||||
.face-frame__text { font-size: 13px; color: rgba(255,255,255,0.4); text-align: center; }
|
||||
|
||||
@keyframes ringPulse {
|
||||
0%, 100% { box-shadow: 0 0 0 0 rgba(74,144,217,0.3); }
|
||||
50% { box-shadow: 0 0 0 12px rgba(74,144,217,0); }
|
||||
}
|
||||
.face-frame.detecting {
|
||||
border-color: #4a90d9; border-style: solid;
|
||||
animation: ringPulse 1.5s infinite;
|
||||
}
|
||||
.face-frame.success {
|
||||
border-color: #52c41a; border-style: solid; background: rgba(82,196,26,0.08);
|
||||
}
|
||||
|
||||
.face-info {
|
||||
text-align: center; min-height: 48px;
|
||||
background: rgba(0,0,0,0.15); border-radius: 10px; padding: 10px 16px; width: 100%;
|
||||
}
|
||||
.face-info__status { font-size: 12px; color: rgba(255,255,255,0.35); display: block; }
|
||||
.face-info__name { font-size: 15px; font-weight: 700; color: #52c41a; display: none; }
|
||||
.face-info__name.show { display: block; }
|
||||
.face-info__detail { font-size: 11px; color: rgba(255,255,255,0.5); margin-top: 4px; display: none; }
|
||||
.face-info__detail.show { display: block; }
|
||||
|
||||
/* 账号密码表单 */
|
||||
.password-section { display: flex; flex-direction: column; gap: 14px; padding: 16px 0; }
|
||||
.password-section.hidden { display: none; }
|
||||
.form-group { display: flex; flex-direction: column; gap: 6px; }
|
||||
.form-label { font-size: 12px; color: rgba(255,255,255,0.6); }
|
||||
.form-input {
|
||||
background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1);
|
||||
border-radius: 8px; padding: 12px 14px; font-size: 14px; color: #fff;
|
||||
outline: none; transition: border-color 0.2s;
|
||||
}
|
||||
.form-input:focus { border-color: #4a90d9; }
|
||||
.form-input::placeholder { color: rgba(255,255,255,0.3); }
|
||||
.login-error { font-size: 12px; color: #ff4d4f; min-height: 16px; }
|
||||
.login-btn {
|
||||
background: #4a90d9; border: none; border-radius: 8px;
|
||||
padding: 12px; font-size: 14px; font-weight: 600; color: #fff;
|
||||
cursor: pointer; transition: all 0.2s; margin-top: 8px;
|
||||
}
|
||||
.login-btn:hover { background: #5ba0e9; transform: translateY(-1px); }
|
||||
.login-btn:active { transform: translateY(0); }
|
||||
.login-hint { font-size: 11px; color: rgba(255,255,255,0.3); text-align: center; }
|
||||
|
||||
/* Toast */
|
||||
.toast {
|
||||
position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px);
|
||||
background: rgba(0,0,0,0.85); color: #fff; padding: 12px 28px; border-radius: 8px;
|
||||
font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden;
|
||||
transition: opacity 0.3s, transform 0.3s, visibility 0.3s;
|
||||
white-space: nowrap; pointer-events: none; max-width: 90%;
|
||||
text-align: center; line-height: 1.5;
|
||||
}
|
||||
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
|
||||
.toast--warn { background: rgba(250,173,22,0.92); }
|
||||
.toast--error { background: rgba(255,77,79,0.92); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="device-frame">
|
||||
<div class="top-bar">
|
||||
<span class="top-bar__title">净菜配比秤 - 员工登录</span>
|
||||
</div>
|
||||
|
||||
<div class="login-main">
|
||||
<div class="login-panel">
|
||||
<div class="login-panel__title">员工登录</div>
|
||||
<div class="login-panel__subtitle">请选择登录方式</div>
|
||||
|
||||
<div class="login-tabs">
|
||||
<div class="login-tab active" data-tab="face" onclick="switchTab('face')">人脸识别</div>
|
||||
<div class="login-tab" data-tab="password" onclick="switchTab('password')">账号密码</div>
|
||||
</div>
|
||||
|
||||
<!-- 人脸识别区 -->
|
||||
<div class="face-section" id="faceSection">
|
||||
<div class="face-frame" id="faceFrame" onclick="startFaceDetect()">
|
||||
<div class="face-frame__icon" id="faceIcon">👤</div>
|
||||
<div class="face-frame__text" id="faceText">点击激活<br>人脸识别</div>
|
||||
</div>
|
||||
<div class="face-info">
|
||||
<span class="face-info__status" id="faceStatus">识别成功后即可进入功能菜单</span>
|
||||
<div class="face-info__name" id="faceName"></div>
|
||||
<div class="face-info__detail" id="faceDetail"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 账号密码表单 -->
|
||||
<div class="password-section hidden" id="passwordSection">
|
||||
<div class="form-group">
|
||||
<label class="form-label">员工工号</label>
|
||||
<input type="text" class="form-input" id="empId" placeholder="请输入员工工号">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">登录密码</label>
|
||||
<input type="password" class="form-input" id="empPassword" placeholder="请输入登录密码">
|
||||
</div>
|
||||
<div class="login-error" id="loginError"></div>
|
||||
<button class="login-btn" onclick="passwordLogin()">登 录</button>
|
||||
<div class="login-hint">演示账号:30001 / 123456</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
var loginState = 'idle';
|
||||
var currentUser = null;
|
||||
var loginTab = 'face';
|
||||
|
||||
var mockUsers = [
|
||||
{ name: '刘九', id: 'EMP-20260050', dept: '打包车间', role: '打包员', empId: '30001', password: '123456' },
|
||||
{ name: '陈十', id: 'EMP-20260055', dept: '打包车间', role: '打包员', empId: '30002', password: '123456' },
|
||||
{ name: '杨一', id: 'EMP-20260060', dept: '质检部', role: '质检员', empId: '30003', password: '123456' }
|
||||
];
|
||||
|
||||
function switchTab(tab) {
|
||||
loginTab = tab;
|
||||
document.querySelectorAll('.login-tab').forEach(function(el) {
|
||||
el.classList.toggle('active', el.dataset.tab === tab);
|
||||
});
|
||||
document.getElementById('faceSection').classList.toggle('hidden', tab !== 'face');
|
||||
document.getElementById('passwordSection').classList.toggle('hidden', tab !== 'password');
|
||||
document.getElementById('loginError').textContent = '';
|
||||
}
|
||||
|
||||
function startFaceDetect() {
|
||||
if (loginState !== 'idle') return;
|
||||
loginState = 'detecting';
|
||||
|
||||
var frame = document.getElementById('faceFrame');
|
||||
var icon = document.getElementById('faceIcon');
|
||||
var text = document.getElementById('faceText');
|
||||
frame.classList.add('detecting');
|
||||
icon.innerHTML = '🔍';
|
||||
text.textContent = '识别中...';
|
||||
showToast('正在识别人脸...', 1500);
|
||||
|
||||
setTimeout(function() {
|
||||
var user = mockUsers[Math.floor(Math.random() * mockUsers.length)];
|
||||
loginSuccess(user);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function passwordLogin() {
|
||||
var empId = document.getElementById('empId').value.trim();
|
||||
var password = document.getElementById('empPassword').value.trim();
|
||||
var errorEl = document.getElementById('loginError');
|
||||
|
||||
if (!empId || !password) { errorEl.textContent = '请输入工号和密码'; return; }
|
||||
|
||||
var user = null;
|
||||
for (var i = 0; i < mockUsers.length; i++) {
|
||||
var u = mockUsers[i];
|
||||
if (u.empId === empId && u.password === password) {
|
||||
user = u; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!user) { errorEl.textContent = '工号或密码错误,请重试'; return; }
|
||||
loginSuccess(user);
|
||||
}
|
||||
|
||||
function loginSuccess(user) {
|
||||
currentUser = user;
|
||||
loginState = 'success';
|
||||
|
||||
var frame = document.getElementById('faceFrame');
|
||||
var icon = document.getElementById('faceIcon');
|
||||
var text = document.getElementById('faceText');
|
||||
frame.classList.remove('detecting');
|
||||
frame.classList.add('success');
|
||||
icon.innerHTML = '✅';
|
||||
text.innerHTML = user.name;
|
||||
|
||||
document.getElementById('faceStatus').style.display = 'none';
|
||||
var nameEl = document.getElementById('faceName');
|
||||
nameEl.textContent = user.name + ' · ' + user.role;
|
||||
nameEl.classList.add('show');
|
||||
var detailEl = document.getElementById('faceDetail');
|
||||
detailEl.textContent = user.dept + ' · ' + user.id;
|
||||
detailEl.classList.add('show');
|
||||
|
||||
showToast('欢迎,' + user.name + ',正在进入功能菜单...', 1500);
|
||||
setTimeout(function() {
|
||||
window.location.href = '00-welcome.html?user=' + encodeURIComponent(user.name) + '&uid=' + user.id;
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function showToast(msg, duration, type) {
|
||||
var el = document.getElementById('toast');
|
||||
el.textContent = msg;
|
||||
el.className = 'toast';
|
||||
if (type === 'warn') el.classList.add('toast--warn');
|
||||
if (type === 'error') el.classList.add('toast--error');
|
||||
el.classList.add('show');
|
||||
clearTimeout(el._timer);
|
||||
el._timer = setTimeout(function() { el.classList.remove('show'); }, duration || 2000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,217 +3,209 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1280, initial-scale=1.0">
|
||||
<title>净菜配比秤 - 欢迎 | 蚁熊智能餐养平台</title>
|
||||
<title>净菜配比秤 - 功能菜单 | 蚁熊智能餐养平台</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden; }
|
||||
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
|
||||
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
|
||||
.back-btn:hover { color: #fff; }
|
||||
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
|
||||
.welcome-main { display: flex; align-items: stretch; height: calc(100% - 44px); padding: 24px 32px; gap: 32px; }
|
||||
.login-panel { flex: 0 0 420px; display: flex; flex-direction: column; gap: 20px; background: #1a2b4a; border-radius: 16px; padding: 24px; }
|
||||
.login-panel__title { font-size: 16px; font-weight: 600; color: rgba(255,255,255,0.8); text-align: center; }
|
||||
.login-tabs { display: flex; gap: 0; border-bottom: 1px solid rgba(255,255,255,0.1); }
|
||||
.login-tab { flex: 1; padding: 10px; text-align: center; font-size: 13px; color: rgba(255,255,255,0.5); cursor: pointer; border-bottom: 2px solid transparent; transition: all 0.2s; }
|
||||
.login-tab:hover { color: rgba(255,255,255,0.8); }
|
||||
.login-tab.active { color: #4a90d9; border-bottom-color: #4a90d9; }
|
||||
.face-section { display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 20px 0; }
|
||||
.face-section.hidden { display: none; }
|
||||
.face-frame { width: 180px; height: 180px; border-radius: 50%; border: 3px dashed rgba(74,144,217,0.4); display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 8px; position: relative; background: rgba(26,43,74,0.3); cursor: pointer; transition: all 0.3s; }
|
||||
.face-frame:hover { border-color: #4a90d9; background: rgba(74,144,217,0.1); }
|
||||
.face-frame__icon { font-size: 40px; color: rgba(255,255,255,0.3); }
|
||||
.face-frame__text { font-size: 12px; color: rgba(255,255,255,0.4); text-align: center; }
|
||||
@keyframes ringPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(74,144,217,0.3); } 50% { box-shadow: 0 0 0 12px rgba(74,144,217,0); } }
|
||||
.face-frame.detecting { border-color: #4a90d9; border-style: solid; animation: ringPulse 1.5s infinite; }
|
||||
.face-frame.success { border-color: #52c41a; border-style: solid; background: rgba(82,196,26,0.08); }
|
||||
.face-info { text-align: center; min-height: 48px; background: rgba(0,0,0,0.15); border-radius: 10px; padding: 10px 16px; width: 100%; }
|
||||
.face-info__status { font-size: 12px; color: rgba(255,255,255,0.35); display: block; }
|
||||
.face-info__name { font-size: 15px; font-weight: 700; color: #52c41a; display: none; }
|
||||
.face-info__name.show { display: block; }
|
||||
.face-info__detail { font-size: 11px; color: rgba(255,255,255,0.5); margin-top: 4px; display: none; }
|
||||
.face-info__detail.show { display: block; }
|
||||
.password-section { display: flex; flex-direction: column; gap: 14px; padding: 16px 0; }
|
||||
.password-section.hidden { display: none; }
|
||||
.form-group { display: flex; flex-direction: column; gap: 6px; }
|
||||
.form-label { font-size: 12px; color: rgba(255,255,255,0.6); }
|
||||
.form-input { background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1); border-radius: 8px; padding: 12px 14px; font-size: 14px; color: #fff; outline: none; transition: border-color 0.2s; }
|
||||
.form-input:focus { border-color: #4a90d9; }
|
||||
.form-input::placeholder { color: rgba(255,255,255,0.3); }
|
||||
.login-btn { background: #4a90d9; border: none; border-radius: 8px; padding: 12px; font-size: 14px; font-weight: 600; color: #fff; cursor: pointer; transition: all 0.2s; margin-top: 8px; }
|
||||
.login-btn:hover { background: #5ba0e9; transform: translateY(-1px); }
|
||||
.menu-panel { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 14px; }
|
||||
.menu-panel__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
|
||||
.menu-panel__title { font-size: 14px; color: rgba(255,255,255,0.4); letter-spacing: 1px; }
|
||||
.menu-panel__user { font-size: 12px; color: rgba(255,255,255,0.5); }
|
||||
.menu-panel__user.show { display: block; }
|
||||
.menu-panel__user.hidden { display: none; }
|
||||
.menu-btn { display: flex; align-items: center; gap: 14px; padding: 16px 20px; border-radius: 12px; background: #1a2b4a; border: 1px solid rgba(255,255,255,0.06); cursor: pointer; transition: all 0.2s; text-decoration: none; color: #fff; }
|
||||
.menu-btn:hover { transform: translateX(4px); border-color: rgba(74,144,217,0.3); box-shadow: 0 4px 16px rgba(0,0,0,0.2); }
|
||||
body {
|
||||
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
|
||||
background: #05080f; color: #fff;
|
||||
min-height: 100vh; min-width: 1280px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* PAD 设备外壳 */
|
||||
.device-frame {
|
||||
width: 1280px; height: 720px;
|
||||
background: #0e1326;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex; flex-direction: column;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.top-bar {
|
||||
display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px;
|
||||
}
|
||||
.top-bar__title {
|
||||
flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85);
|
||||
}
|
||||
.top-bar__user {
|
||||
font-size: 12px; color: rgba(255,255,255,0.5);
|
||||
}
|
||||
.logout-btn {
|
||||
font-size: 12px; color: rgba(255,255,255,0.5); cursor: pointer;
|
||||
padding: 4px 12px; border-radius: 4px; transition: all 0.2s;
|
||||
border: 1px solid rgba(255,255,255,0.15); background: none; margin-left: 10px;
|
||||
}
|
||||
.logout-btn:hover { color: #fff; border-color: rgba(255,255,255,0.3); }
|
||||
|
||||
/* 主内容:菜单按钮列居中 */
|
||||
.menu-main {
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
height: calc(100% - 44px); padding: 24px 32px;
|
||||
}
|
||||
|
||||
.menu-panel {
|
||||
width: 560px; display: flex; flex-direction: column; gap: 14px;
|
||||
}
|
||||
.menu-panel__header {
|
||||
display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;
|
||||
}
|
||||
.menu-panel__title {
|
||||
font-size: 14px; color: rgba(255,255,255,0.4); letter-spacing: 1px;
|
||||
}
|
||||
.menu-panel__user {
|
||||
font-size: 12px; color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.menu-btn {
|
||||
display: flex; align-items: center; gap: 14px;
|
||||
padding: 16px 20px; border-radius: 12px;
|
||||
background: #1a2b4a; border: 1px solid rgba(255,255,255,0.06);
|
||||
cursor: pointer; transition: all 0.2s; text-decoration: none; color: #fff;
|
||||
position: relative;
|
||||
}
|
||||
.menu-btn:hover {
|
||||
transform: translateX(4px); border-color: rgba(74,144,217,0.3);
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
|
||||
}
|
||||
.menu-btn:active { transform: translateX(2px) scale(0.99); }
|
||||
.menu-btn.disabled { opacity: 0.4; cursor: not-allowed; transform: none !important; box-shadow: none !important; border-color: transparent !important; }
|
||||
.menu-btn__icon { width: 44px; height: 44px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0; }
|
||||
.menu-btn__icon {
|
||||
width: 44px; height: 44px; border-radius: 10px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 22px; flex-shrink: 0;
|
||||
}
|
||||
.menu-btn__icon--blue { background: rgba(74,144,217,0.15); }
|
||||
.menu-btn__icon--green { background: rgba(82,196,26,0.15); }
|
||||
.menu-btn__icon--orange { background: rgba(250,173,22,0.15); }
|
||||
.menu-btn__icon--purple { background: rgba(114,46,209,0.15); }
|
||||
.menu-btn__icon--gray { background: rgba(255,255,255,0.08); }
|
||||
.menu-btn__info { flex: 1; }
|
||||
.menu-btn__title { font-size: 15px; font-weight: 600; margin-bottom: 2px; }
|
||||
.menu-btn__desc { font-size: 12px; color: rgba(255,255,255,0.4); }
|
||||
.menu-btn__arrow { font-size: 16px; color: rgba(255,255,255,0.25); flex-shrink: 0; }
|
||||
.toast { position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px); background: rgba(0,0,0,0.85); color: #fff; padding: 12px 28px; border-radius: 8px; font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity 0.3s, transform 0.3s, visibility 0.3s; white-space: nowrap; pointer-events: none; max-width: 90%; text-align: center; line-height: 1.5; }
|
||||
|
||||
/* 任务到达提示 */
|
||||
.menu-btn--has-tasks {
|
||||
border-color: rgba(74,144,217,0.5) !important;
|
||||
animation: menuPulse 2s ease-in-out infinite;
|
||||
}
|
||||
@keyframes menuPulse {
|
||||
0%, 100% { box-shadow: 0 0 0 0 rgba(74,144,217,0.4); }
|
||||
50% { box-shadow: 0 0 0 6px rgba(74,144,217,0); }
|
||||
}
|
||||
.menu-btn__badge {
|
||||
position: absolute; top: -6px; right: -6px;
|
||||
background: #ff4d4f; color: #fff;
|
||||
font-size: 10px; font-weight: 700;
|
||||
min-width: 18px; height: 18px; border-radius: 9px;
|
||||
display: none; align-items: center; justify-content: center;
|
||||
padding: 0 4px; line-height: 1;
|
||||
}
|
||||
|
||||
/* Toast */
|
||||
.toast {
|
||||
position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px);
|
||||
background: rgba(0,0,0,0.85); color: #fff; padding: 12px 28px; border-radius: 8px;
|
||||
font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden;
|
||||
transition: opacity 0.3s, transform 0.3s, visibility 0.3s;
|
||||
white-space: nowrap; pointer-events: none; max-width: 90%;
|
||||
text-align: center; line-height: 1.5;
|
||||
}
|
||||
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
|
||||
.toast--warn { background: rgba(250,173,22,0.92); }
|
||||
.toast--error { background: rgba(255,77,79,0.92); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<span class="top-bar__title">净菜配比秤</span>
|
||||
</div>
|
||||
<div class="welcome-main">
|
||||
<div class="login-panel">
|
||||
<div class="login-panel__title">员工登录</div>
|
||||
<div class="login-tabs">
|
||||
<div class="login-tab active" data-tab="face" onclick="switchTab('face')">人脸识别</div>
|
||||
<div class="login-tab" data-tab="password" onclick="switchTab('password')">账号密码</div>
|
||||
</div>
|
||||
<div class="face-section" id="faceSection">
|
||||
<div class="face-frame" id="faceFrame" onclick="startFaceDetect()">
|
||||
<div class="face-frame__icon" id="faceIcon">👤</div>
|
||||
<div class="face-frame__text" id="faceText">点击激活<br>人脸识别</div>
|
||||
|
||||
<div class="device-frame">
|
||||
<div class="top-bar">
|
||||
<span class="top-bar__title">净菜配比秤 - 功能菜单</span>
|
||||
<span class="top-bar__user" id="topUser">--</span>
|
||||
<button class="logout-btn" onclick="handleLogout()">退出登录</button>
|
||||
</div>
|
||||
|
||||
<div class="menu-main">
|
||||
<div class="menu-panel">
|
||||
<div class="menu-panel__header">
|
||||
<div class="menu-panel__title">📌 功能菜单</div>
|
||||
<div class="menu-panel__user" id="menuUser"></div>
|
||||
</div>
|
||||
<div class="face-info">
|
||||
<span class="face-info__status" id="faceStatus">识别成功后即可使用各项功能</span>
|
||||
<div class="face-info__name" id="faceName"></div>
|
||||
<div class="face-info__detail" id="faceDetail"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="password-section hidden" id="passwordSection">
|
||||
<div class="form-group">
|
||||
<label class="form-label">员工工号</label>
|
||||
<input type="text" class="form-input" id="empId" placeholder="请输入员工工号">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">登录密码</label>
|
||||
<input type="password" class="form-input" id="empPassword" placeholder="请输入登录密码">
|
||||
</div>
|
||||
<button class="login-btn" onclick="passwordLogin()">登录</button>
|
||||
|
||||
<a class="menu-btn" id="btnTasks" onclick="handleMenu('01-packing-tasks.html')">
|
||||
<div class="menu-btn__icon menu-btn__icon--blue">📋</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">称重任务</div>
|
||||
<div class="menu-btn__desc">查看系统分配的称重任务清单</div>
|
||||
</div>
|
||||
<span class="menu-btn__badge" id="taskBadge">0</span>
|
||||
<div class="menu-btn__arrow">›</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-panel">
|
||||
<div class="menu-panel__header">
|
||||
<div class="menu-panel__title">📌 功能菜单</div>
|
||||
<div class="menu-panel__user hidden" id="menuUser"></div>
|
||||
</div>
|
||||
<a class="menu-btn disabled" id="btnTasks" onclick="handleMenu('01-packing-tasks.html')">
|
||||
<div class="menu-btn__icon menu-btn__icon--blue">📋</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">今日任务</div>
|
||||
<div class="menu-btn__desc">查看系统分配的打包任务清单</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</div>
|
||||
</a>
|
||||
<a class="menu-btn disabled" id="btnPacking" onclick="handleMenu('02-weighing-packing.html')">
|
||||
<div class="menu-btn__icon menu-btn__icon--green">📦</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">称重打包</div>
|
||||
<div class="menu-btn__desc">净菜识别、称重、按单打包</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</div>
|
||||
</a>
|
||||
<a class="menu-btn disabled" id="btnHistory" onclick="handleMenu('03-history.html')">
|
||||
<div class="menu-btn__icon menu-btn__icon--orange">📝</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">打包记录</div>
|
||||
<div class="menu-btn__desc">历史打包记录查看与筛选</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</div>
|
||||
</a>
|
||||
<a class="menu-btn disabled" id="btnSettings" onclick="handleMenu('04-settings.html')">
|
||||
<div class="menu-btn__icon menu-btn__icon--gray">⚙️</div>
|
||||
<div class="menu-btn__info">
|
||||
<div class="menu-btn__title">设备设置</div>
|
||||
<div class="menu-btn__desc">设备参数配置与状态查看</div>
|
||||
</div>
|
||||
<div class="menu-btn__arrow">›</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
var loginState = 'idle';
|
||||
var currentUser = null;
|
||||
var loginTab = 'face';
|
||||
var mockUsers = [
|
||||
{ name: '刘九', id: 'EMP-20260050', dept: '打包车间', role: '打包员', empId: '30001', password: '123456' },
|
||||
{ name: '陈十', id: 'EMP-20260055', dept: '打包车间', role: '打包员', empId: '30002', password: '123456' },
|
||||
{ name: '杨一', id: 'EMP-20260060', dept: '质检部', role: '质检员', empId: '30003', password: '123456' }
|
||||
];
|
||||
var menuButtons = ['btnTasks', 'btnPacking', 'btnHistory', 'btnSettings'];
|
||||
|
||||
function switchTab(tab) {
|
||||
loginTab = tab;
|
||||
document.querySelectorAll('.login-tab').forEach(function(el) { el.classList.toggle('active', el.dataset.tab === tab); });
|
||||
document.getElementById('faceSection').classList.toggle('hidden', tab !== 'face');
|
||||
document.getElementById('passwordSection').classList.toggle('hidden', tab !== 'password');
|
||||
// 获取 URL 参数
|
||||
function getUrlParam(name) {
|
||||
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
|
||||
var r = window.location.search.substr(1).match(reg);
|
||||
if (r !== null) return decodeURIComponent(r[2]);
|
||||
return null;
|
||||
}
|
||||
|
||||
function startFaceDetect() {
|
||||
if (loginState !== 'idle') return;
|
||||
loginState = 'detecting';
|
||||
var frame = document.getElementById('faceFrame');
|
||||
var icon = document.getElementById('faceIcon');
|
||||
var text = document.getElementById('faceText');
|
||||
frame.classList.add('detecting');
|
||||
icon.innerHTML = '🔍';
|
||||
text.textContent = '识别中...';
|
||||
showToast('正在识别人脸...', 1500);
|
||||
setTimeout(function() {
|
||||
var user = mockUsers[Math.floor(Math.random() * mockUsers.length)];
|
||||
loginSuccess(user);
|
||||
}, 2000);
|
||||
}
|
||||
// 页面加载时检查登录状态
|
||||
(function() {
|
||||
var userName = getUrlParam('user');
|
||||
var userId = getUrlParam('uid');
|
||||
|
||||
function passwordLogin() {
|
||||
var empId = document.getElementById('empId').value.trim();
|
||||
var password = document.getElementById('empPassword').value.trim();
|
||||
if (!empId || !password) { showToast('请输入工号和密码', 2000, 'warn'); return; }
|
||||
var user = mockUsers.find(function(u) { return u.empId === empId && u.password === password; });
|
||||
if (!user) { showToast('工号或密码错误', 2000, 'error'); return; }
|
||||
loginSuccess(user);
|
||||
}
|
||||
if (!userName || !userId) {
|
||||
// 未登录,跳转到登录页
|
||||
window.location.href = '00-login.html';
|
||||
return;
|
||||
}
|
||||
|
||||
function loginSuccess(user) {
|
||||
currentUser = user;
|
||||
loginState = 'success';
|
||||
var frame = document.getElementById('faceFrame');
|
||||
var icon = document.getElementById('faceIcon');
|
||||
var text = document.getElementById('faceText');
|
||||
frame.classList.remove('detecting');
|
||||
frame.classList.add('success');
|
||||
icon.innerHTML = '✅';
|
||||
text.innerHTML = user.name;
|
||||
document.getElementById('faceStatus').style.display = 'none';
|
||||
var nameEl = document.getElementById('faceName');
|
||||
nameEl.textContent = user.name + ' · ' + user.role;
|
||||
nameEl.classList.add('show');
|
||||
var detailEl = document.getElementById('faceDetail');
|
||||
detailEl.textContent = user.dept + ' · ' + user.id;
|
||||
detailEl.classList.add('show');
|
||||
var menuUser = document.getElementById('menuUser');
|
||||
menuUser.textContent = '当前用户:' + user.name;
|
||||
menuUser.classList.remove('hidden');
|
||||
menuButtons.forEach(function(id) { document.getElementById(id).classList.remove('disabled'); });
|
||||
showToast('欢迎,' + user.name, 2000);
|
||||
currentUser = { name: userName, id: userId };
|
||||
|
||||
// 显示用户信息
|
||||
document.getElementById('topUser').textContent = '操作员:' + userName;
|
||||
document.getElementById('menuUser').textContent = '当前用户:' + userName;
|
||||
|
||||
// 启动任务轮询(每 30 秒检测新任务)
|
||||
setTimeout(function() { checkNewTasks(5); }, 1500);
|
||||
setInterval(function() { checkNewTasks(5); }, 30000);
|
||||
})();
|
||||
|
||||
// 检测新任务到达
|
||||
function checkNewTasks(count) {
|
||||
var btn = document.getElementById('btnTasks');
|
||||
var badge = document.getElementById('taskBadge');
|
||||
btn.classList.add('menu-btn--has-tasks');
|
||||
badge.textContent = count;
|
||||
badge.style.display = 'flex';
|
||||
showToast('⚡ 新任务已到达(' + count + ' 条待处理)', 2500);
|
||||
}
|
||||
|
||||
// 菜单点击处理
|
||||
function handleMenu(target) {
|
||||
if (loginState !== 'success' || !currentUser) { showToast('请先登录', 2000, 'warn'); return; }
|
||||
if (!currentUser) {
|
||||
window.location.href = '00-login.html';
|
||||
return;
|
||||
}
|
||||
window.location.href = target + '?user=' + encodeURIComponent(currentUser.name) + '&uid=' + currentUser.id;
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
function handleLogout() {
|
||||
window.location.href = '00-login.html';
|
||||
}
|
||||
|
||||
// Toast 提示
|
||||
function showToast(msg, duration, type) {
|
||||
var el = document.getElementById('toast');
|
||||
el.textContent = msg;
|
||||
|
||||
@@ -3,415 +3,157 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1280, initial-scale=1.0">
|
||||
<title>净菜配比秤 - 今日任务 | 蚁熊智能餐养平台</title>
|
||||
<title>净菜配比秤 - 称重任务 | 蚁熊智能餐养平台</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden; }
|
||||
body {
|
||||
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
|
||||
background: #05080f; color: #fff;
|
||||
min-height: 100vh; min-width: 1280px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
/* PAD 设备外壳 */
|
||||
.device-frame {
|
||||
width: 1280px; height: 720px;
|
||||
background: #0e1326;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex; flex-direction: column;
|
||||
}
|
||||
|
||||
/* 顶部栏 */
|
||||
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
|
||||
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
|
||||
.back-btn:hover { color: #fff; }
|
||||
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
|
||||
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
|
||||
.main-content { height: calc(100% - 44px); padding: 20px 28px; display: flex; flex-direction: column; gap: 16px; }
|
||||
|
||||
/* 状态标签卡(统计+筛选二合一) */
|
||||
.tasks-tabs { display: flex; gap: 10px; }
|
||||
.status-tab {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
padding: 10px 20px; border-radius: 8px;
|
||||
background: #1a2b4a; border: 1px solid rgba(255,255,255,0.06);
|
||||
cursor: pointer; transition: all 0.2s; user-select: none;
|
||||
}
|
||||
.status-tab:hover { border-color: rgba(255,255,255,0.15); }
|
||||
.status-tab.active--pending { background: rgba(250,173,22,0.15); border-color: rgba(250,173,22,0.4); }
|
||||
.status-tab.active--done { background: rgba(82,196,26,0.15); border-color: rgba(82,196,26,0.4); }
|
||||
.status-tab__label { font-size: 13px; font-weight: 500; color: rgba(255,255,255,0.7); }
|
||||
.status-tab__count { font-size: 20px; font-weight: 700; color: #fff; }
|
||||
/* 主内容区 */
|
||||
.main-content { height: calc(100% - 44px); padding: 16px 24px; display: flex; flex-direction: column; gap: 12px; }
|
||||
|
||||
.tasks-section { flex: 1; display: flex; flex-direction: column; gap: 12px; overflow: hidden; }
|
||||
.task-list {
|
||||
flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 10px;
|
||||
padding-right: 4px; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.1) transparent;
|
||||
/* Tab 切换栏 */
|
||||
.tabs { display: flex; gap: 8px; }
|
||||
.tab { padding: 8px 20px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.2s; border: 1px solid rgba(255,255,255,0.08); background: transparent; color: rgba(255,255,255,0.6); }
|
||||
.tab:hover { background: rgba(255,255,255,0.04); color: rgba(255,255,255,0.9); }
|
||||
.tab.active { background: #4a90d9; border-color: #4a90d9; color: #fff; }
|
||||
.tab__count { margin-left: 6px; font-size: 11px; opacity: 0.8; }
|
||||
|
||||
/* 任务列表容器 */
|
||||
.task-list-container { flex: 1; overflow-y: auto; scrollbar-width: none; }
|
||||
.task-list-container::-webkit-scrollbar { display: none; }
|
||||
|
||||
/* 任务卡片 */
|
||||
.task-card { background: #1a2b4a; border-radius: 10px; padding: 0; margin-bottom: 8px; border: 1px solid rgba(255,255,255,0.06); transition: all 0.2s; overflow: hidden; }
|
||||
.task-card:hover { border-color: rgba(74,144,217,0.3); }
|
||||
.task-card__header { display: flex; align-items: center; padding: 10px 16px; gap: 14px; background: rgba(26,43,74,0.6); border-bottom: 1px solid rgba(255,255,255,0.06); }
|
||||
.task-card__order-info { font-size: 13px; color: rgba(255,255,255,0.7); display: flex; align-items: center; gap: 4px; }
|
||||
.task-card__order-info__label { color: rgba(255,255,255,0.4); }
|
||||
.task-card__order-info__value { color: #4a90d9; font-weight: 600; }
|
||||
.task-card__arrival { font-size: 12px; color: rgba(255,255,255,0.5); display: flex; align-items: center; gap: 4px; }
|
||||
.task-card__arrival__time { color: #faad16; font-weight: 500; }
|
||||
.task-card__status { margin-left: auto; }
|
||||
.task-card__pack-btn { padding: 5px 14px; border-radius: 5px; font-size: 12px; font-weight: 500; border: none; cursor: pointer; transition: all 0.2s; background: #4a90d9; color: #fff; }
|
||||
.task-card__pack-btn:hover { background: #5ba0e9; }
|
||||
.task-card__pack-btn:disabled { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.4); cursor: not-allowed; }
|
||||
|
||||
/* 表格头(6列) */
|
||||
.item-table__head {
|
||||
display: grid; grid-template-columns: 1.6fr 0.8fr 0.7fr 0.9fr 0.9fr 70px; gap: 8px;
|
||||
padding: 6px 16px; background: rgba(0,0,0,0.2); font-size: 11px; color: rgba(255,255,255,0.4); font-weight: 500;
|
||||
}
|
||||
.task-list::-webkit-scrollbar { width: 4px; }
|
||||
.task-list::-webkit-scrollbar-track { background: transparent; }
|
||||
.task-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
|
||||
.task-item {
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
background: #1a2b4a; border-radius: 12px; padding: 16px 20px;
|
||||
border: 1px solid rgba(255,255,255,0.06); cursor: pointer; transition: all 0.2s;
|
||||
.item-table__body { display: flex; flex-direction: column; }
|
||||
|
||||
/* 餐品净菜包主行 */
|
||||
.item-parent-row {
|
||||
display: grid; grid-template-columns: 1.6fr 0.8fr 0.7fr 0.9fr 0.9fr 70px; gap: 8px;
|
||||
padding: 10px 16px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center;
|
||||
background: rgba(74,144,217,0.06);
|
||||
}
|
||||
.task-item:hover { border-color: rgba(74,144,217,0.3); box-shadow: 0 4px 16px rgba(0,0,0,0.2); }
|
||||
.task-icon { width: 52px; height: 52px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 26px; flex-shrink: 0; }
|
||||
.task-icon--potato { background: rgba(250,173,22,0.15); }
|
||||
.task-icon--tomato { background: rgba(255,77,79,0.15); }
|
||||
.task-icon--cabbage { background: rgba(82,196,26,0.15); }
|
||||
.task-icon--carrot { background: rgba(250,140,22,0.15); }
|
||||
.task-icon--cucumber { background: rgba(20,184,166,0.15); }
|
||||
.task-info { flex: 1; display: flex; flex-direction: column; gap: 4px; }
|
||||
.task-name { font-size: 15px; font-weight: 600; color: #fff; }
|
||||
.task-detail { font-size: 12px; color: rgba(255,255,255,0.5); display: flex; gap: 12px; }
|
||||
.task-detail__item { display: flex; align-items: center; gap: 4px; }
|
||||
.task-target { display: flex; align-items: center; gap: 6px; padding: 4px 10px; background: rgba(74,144,217,0.15); border-radius: 4px; font-size: 11px; color: #4a90d9; }
|
||||
.task-progress { width: 140px; display: flex; flex-direction: column; gap: 4px; }
|
||||
.progress-bar { height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; overflow: hidden; }
|
||||
.progress-bar__fill { height: 100%; border-radius: 3px; }
|
||||
.progress-bar__fill--blue { background: #4a90d9; }
|
||||
.progress-bar__fill--green { background: #52c41a; }
|
||||
.progress-text { font-size: 11px; color: rgba(255,255,255,0.5); text-align: right; }
|
||||
.task-status { width: 80px; text-align: center; }
|
||||
.status-badge { display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 500; }
|
||||
.parent-name { display: flex; align-items: center; gap: 8px; }
|
||||
.parent-icon {
|
||||
width: 32px; height: 32px; border-radius: 6px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 16px; background: rgba(114,46,209,0.15); flex-shrink: 0;
|
||||
}
|
||||
.parent-name__text { font-size: 13px; font-weight: 600; color: #fff; }
|
||||
.pack-size-tag {
|
||||
display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 4px;
|
||||
background: rgba(74,144,217,0.15); color: #4a90d9; font-weight: 500;
|
||||
}
|
||||
.parent-weight { font-size: 12px; color: rgba(255,255,255,0.6); text-align: right; }
|
||||
.parent-weight--done { color: #52c41a; font-weight: 600; }
|
||||
|
||||
/* 食材子行 */
|
||||
.item-child-row {
|
||||
display: grid; grid-template-columns: 1.6fr 0.8fr 0.7fr 0.9fr 0.9fr 70px; gap: 8px;
|
||||
padding: 8px 16px 8px 48px; border-top: 1px solid rgba(255,255,255,0.03);
|
||||
align-items: center; transition: background 0.2s;
|
||||
}
|
||||
.item-child-row:hover { background: rgba(74,144,217,0.08); }
|
||||
.child-name { display: flex; align-items: center; gap: 8px; }
|
||||
.child-icon {
|
||||
width: 26px; height: 26px; border-radius: 5px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 13px; flex-shrink: 0;
|
||||
}
|
||||
.child-icon--potato { background: rgba(250,173,22,0.15); }
|
||||
.child-icon--carrot { background: rgba(250,140,22,0.15); }
|
||||
.child-icon--cucumber { background: rgba(20,184,166,0.15); }
|
||||
.child-icon--cabbage { background: rgba(82,196,26,0.15); }
|
||||
.child-icon--tomato { background: rgba(255,77,79,0.15); }
|
||||
.child-icon--egg { background: rgba(250,173,22,0.15); }
|
||||
.child-icon--onion { background: rgba(114,46,209,0.15); }
|
||||
.child-icon--green-onion { background: rgba(82,196,26,0.15); }
|
||||
.child-name__text { font-size: 12px; color: rgba(255,255,255,0.85); }
|
||||
.child-weight { font-size: 12px; color: rgba(255,255,255,0.55); text-align: right; }
|
||||
.child-weight--done { color: #52c41a; font-weight: 600; }
|
||||
.child-pack-size { font-size: 12px; color: rgba(255,255,255,0.45); text-align: center; }
|
||||
|
||||
/* 状态徽章 */
|
||||
.status-badge { font-size: 11px; padding: 3px 8px; border-radius: 4px; font-weight: 500; display: inline-block; }
|
||||
.status-badge--pending { background: rgba(250,173,22,0.15); color: #faad16; }
|
||||
.status-badge--done { background: rgba(82,196,26,0.15); color: #52c41a; }
|
||||
.task-action { width: 80px; }
|
||||
.action-btn { padding: 8px 16px; border-radius: 6px; font-size: 12px; font-weight: 500; background: #4a90d9; color: #fff; border: none; cursor: pointer; transition: all 0.2s; }
|
||||
.action-btn:hover { background: #5ba0e9; }
|
||||
.action-btn--done { background: rgba(82,196,26,0.15); color: #52c41a; cursor: default; }
|
||||
.status-tag {
|
||||
display: inline-block; padding: 2px 6px; border-radius: 4px; font-size: 10px;
|
||||
}
|
||||
.status-tag--done { background: rgba(82,196,26,0.15); color: #52c41a; }
|
||||
.status-tag--wait { background: rgba(250,173,22,0.15); color: #faad16; }
|
||||
|
||||
/* 弹窗遮罩层 */
|
||||
.modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.6); z-index: 900; display: none; align-items: center; justify-content: center; }
|
||||
.modal-overlay.open { display: flex; }
|
||||
.modal-box { width: 1220px; height: 660px; background: #0e1326; border-radius: 16px; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 64px rgba(0,0,0,0.7); }
|
||||
.modal-header { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
|
||||
.modal-close { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); transition: color 0.2s; background: none; border: none; }
|
||||
.modal-close:hover { color: #fff; }
|
||||
.modal-title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
|
||||
.modal-body { flex: 1; display: flex; gap: 20px; padding: 16px 20px; overflow: hidden; }
|
||||
.modal-scale-panel { flex: 0 0 540px; display: flex; flex-direction: column; gap: 12px; }
|
||||
.modal-task { background: #1a2b4a; border-radius: 12px; padding: 12px 16px; border: 1px solid rgba(255,255,255,0.06); }
|
||||
.modal-task__body { display: flex; align-items: center; gap: 12px; }
|
||||
.modal-task__icon { width: 44px; height: 44px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 22px; }
|
||||
.modal-task__info { flex: 1; }
|
||||
.modal-task__name { font-size: 15px; font-weight: 600; color: #fff; margin-bottom: 2px; }
|
||||
.modal-task__target { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; background: rgba(74,144,217,0.15); border-radius: 4px; font-size: 11px; color: #4a90d9; }
|
||||
.modal-task__progress { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
|
||||
.progress-mini { width: 80px; height: 4px; background: rgba(255,255,255,0.1); border-radius: 2px; overflow: hidden; }
|
||||
.progress-mini__fill { height: 100%; background: #4a90d9; border-radius: 2px; }
|
||||
.progress-mini__text { font-size: 11px; color: rgba(255,255,255,0.5); }
|
||||
.scale-display { flex: 1; background: #1a2b4a; border-radius: 14px; padding: 18px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; border: 2px solid rgba(255,255,255,0.06); }
|
||||
.scale-display.weighing { border-color: #4a90d9; }
|
||||
.scale-display.stable { border-color: #52c41a; }
|
||||
.ai-result { display: flex; align-items: center; gap: 14px; padding: 14px 18px; background: rgba(0,0,0,0.2); border-radius: 10px; width: 100%; }
|
||||
.ai-result__icon { width: 48px; height: 48px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 26px; background: rgba(74,144,217,0.15); }
|
||||
.ai-result__info { flex: 1; }
|
||||
.ai-result__label { font-size: 11px; color: rgba(255,255,255,0.4); margin-bottom: 2px; }
|
||||
.ai-result__name { font-size: 18px; font-weight: 700; color: #fff; }
|
||||
.ai-result__confidence { font-size: 12px; color: rgba(255,255,255,0.5); margin-top: 2px; }
|
||||
.ai-result__status { font-size: 12px; padding: 4px 10px; border-radius: 4px; }
|
||||
.ai-result__status--matching { background: rgba(82,196,26,0.15); color: #52c41a; }
|
||||
.ai-result__status--mismatch { background: rgba(255,77,79,0.15); color: #ff4d4f; }
|
||||
.ai-result__status--idle { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.4); }
|
||||
.weight-display { text-align: center; }
|
||||
.weight-display__value { font-size: 60px; font-weight: 700; color: #fff; line-height: 1; font-family: "Courier New", monospace; }
|
||||
.weight-display__unit { font-size: 18px; color: rgba(255,255,255,0.5); margin-left: 4px; }
|
||||
.weight-display__status { font-size: 13px; color: rgba(255,255,255,0.4); margin-top: 6px; }
|
||||
.weight-display__status.weighing { color: #4a90d9; }
|
||||
.weight-display__status.stable { color: #52c41a; }
|
||||
.scale-actions { display: flex; gap: 12px; width: 100%; }
|
||||
.scale-btn { flex: 1; padding: 12px; border-radius: 10px; font-size: 14px; font-weight: 600; border: none; cursor: pointer; transition: all 0.2s; }
|
||||
.scale-btn--primary { background: #52c41a; color: #fff; }
|
||||
.scale-btn--primary:hover { background: #62d42a; }
|
||||
.scale-btn--primary:disabled { background: rgba(82,196,26,0.3); cursor: not-allowed; }
|
||||
.scale-btn--secondary { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
|
||||
.scale-btn--secondary:hover { background: rgba(255,255,255,0.12); }
|
||||
.modal-records-panel { flex: 1; display: flex; flex-direction: column; gap: 12px; }
|
||||
.modal-records { flex: 1; background: #1a2b4a; border-radius: 12px; padding: 14px 16px; display: flex; flex-direction: column; overflow: hidden; }
|
||||
.modal-records__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
|
||||
.modal-records__title { font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.8); }
|
||||
.modal-records__count { font-size: 12px; color: rgba(255,255,255,0.4); }
|
||||
.modal-records__list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.1) transparent; }
|
||||
.modal-records__list::-webkit-scrollbar { width: 4px; }
|
||||
.modal-records__list::-webkit-scrollbar-track { background: transparent; }
|
||||
.modal-records__list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
|
||||
.modal-record { display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: rgba(0,0,0,0.15); border-radius: 8px; }
|
||||
.modal-record__icon { width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; background: rgba(250,173,22,0.15); }
|
||||
.modal-record__info { flex: 1; }
|
||||
.modal-record__name { font-size: 12px; font-weight: 500; color: #fff; }
|
||||
.modal-record__target { font-size: 11px; color: #4a90d9; }
|
||||
.modal-record__time { font-size: 10px; color: rgba(255,255,255,0.3); }
|
||||
.modal-record__weight { font-size: 13px; font-weight: 600; color: #52c41a; }
|
||||
.modal-record__seal { font-size: 11px; padding: 2px 6px; background: rgba(74,144,217,0.15); border-radius: 3px; color: #4a90d9; }
|
||||
.modal-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: rgba(255,255,255,0.3); }
|
||||
.modal-empty__icon { font-size: 28px; margin-bottom: 8px; }
|
||||
.modal-empty__text { font-size: 12px; }
|
||||
|
||||
.toast { position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px); background: rgba(0,0,0,0.85); color: #fff; padding: 12px 28px; border-radius: 8px; font-size: 13px; z-index: 1100; opacity: 0; visibility: hidden; transition: opacity 0.3s, transform 0.3s, visibility 0.3s; white-space: nowrap; pointer-events: none; }
|
||||
/* Toast 提示 */
|
||||
.toast { position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px); background: rgba(0,0,0,0.85); color: #fff; padding: 12px 28px; border-radius: 8px; font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity 0.3s, transform 0.3s, visibility 0.3s; white-space: nowrap; pointer-events: none; }
|
||||
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
|
||||
.toast--error { background: rgba(255,77,79,0.92); }
|
||||
.toast--success { background: rgba(82,196,26,0.92); }
|
||||
.toast--warn { background: rgba(250,173,22,0.92); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<div class="device-frame">
|
||||
<div class="top-bar">
|
||||
<a class="back-btn" id="backBtn" href="javascript:void(0)">◀ 返回</a>
|
||||
<span class="top-bar__title">称重任务</span>
|
||||
<span class="top-bar__user" id="topUser">--</span>
|
||||
</div>
|
||||
|
||||
<a class="back-btn" id="backBtn" href="javascript:void(0)">◀ 返回</a> <span class="top-bar__title">今日打包任务</span>
|
||||
<span class="top-bar__user" id="topUser">--</span>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<!-- 状态标签卡(统计+筛选) -->
|
||||
<div class="tasks-tabs">
|
||||
<div class="status-tab active--pending" data-filter="pending" onclick="filterTasks('pending', this)">
|
||||
<span class="status-tab__label">待处理</span>
|
||||
<span class="status-tab__count" id="pendingCount">4</span>
|
||||
<div class="main-content">
|
||||
<!-- Tab 切换 -->
|
||||
<div class="tabs">
|
||||
<div class="tab active" data-filter="pending" onclick="switchTab('pending', this)">待称重 <span class="tab__count" id="pendingCount">0</span></div>
|
||||
<div class="tab" data-filter="done" onclick="switchTab('done', this)">已完成 <span class="tab__count" id="doneCount">0</span></div>
|
||||
</div>
|
||||
<div class="status-tab" data-filter="done" onclick="filterTasks('done', this)">
|
||||
<span class="status-tab__label">已完成</span>
|
||||
<span class="status-tab__count" id="doneCount">6</span>
|
||||
|
||||
<!-- 任务列表 -->
|
||||
<div class="task-list-container" id="taskListContainer">
|
||||
<!-- 动态渲染 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="tasks-section">
|
||||
<div class="task-list" id="taskList">
|
||||
<!-- 任务项1 -->
|
||||
<div class="task-item" data-status="pending">
|
||||
<div class="task-icon task-icon--potato">🥔</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">土豆丝</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 5.0斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 11:30</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 张三</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--blue" style="width: 60%"></div></div>
|
||||
<div class="progress-text">已包 3.0 / 需 5.0 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--pending">待处理</span></div>
|
||||
<div class="task-action"><button class="action-btn" onclick="openModal('potato')">去处理</button></div>
|
||||
</div>
|
||||
<!-- 任务项2 -->
|
||||
<div class="task-item" data-status="pending">
|
||||
<div class="task-icon task-icon--carrot">🥕</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">胡萝卜丝</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 2.8斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 12:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 李四</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--blue" style="width: 0%"></div></div>
|
||||
<div class="progress-text">已包 0 / 需 2.8 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--pending">待处理</span></div>
|
||||
<div class="task-action"><button class="action-btn" onclick="openModal('carrot')">去处理</button></div>
|
||||
</div>
|
||||
<!-- 任务项3 -->
|
||||
<div class="task-item" data-status="done">
|
||||
<div class="task-icon task-icon--cucumber">🥒</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">黄瓜片</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 4.2斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 11:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 王五</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--green" style="width: 100%"></div></div>
|
||||
<div class="progress-text">已包 4.2 / 需 4.2 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="task-action"><button class="action-btn action-btn--done">完成</button></div>
|
||||
</div>
|
||||
<!-- 任务项4 -->
|
||||
<div class="task-item" data-status="done">
|
||||
<div class="task-icon task-icon--cabbage">🥬</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">白菜段</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 8.5斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 10:30</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 赵六</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--green" style="width: 100%"></div></div>
|
||||
<div class="progress-text">已包 8.5 / 需 8.5 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="task-action"><button class="action-btn action-btn--done">完成</button></div>
|
||||
</div>
|
||||
<!-- 任务项5 -->
|
||||
<div class="task-item" data-status="pending">
|
||||
<div class="task-icon task-icon--tomato">🍅</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">西红柿块</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 3.5斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 12:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 孙七</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--blue" style="width: 0%"></div></div>
|
||||
<div class="progress-text">已包 0 / 需 3.5 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--pending">待处理</span></div>
|
||||
<div class="task-action"><button class="action-btn" onclick="openModal('tomato')">去处理</button></div>
|
||||
</div>
|
||||
<!-- 任务项6 -->
|
||||
<div class="task-item" data-status="pending">
|
||||
<div class="task-icon task-icon--potato">🥔</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">土豆块(晚餐)</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 3.2斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 16:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 张三</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--blue" style="width: 30%"></div></div>
|
||||
<div class="progress-text">已包 1.0 / 需 3.2 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--pending">待处理</span></div>
|
||||
<div class="task-action"><button class="action-btn" onclick="openModal('potato_dinner')">去处理</button></div>
|
||||
</div>
|
||||
<!-- 任务项7 -->
|
||||
<div class="task-item" data-status="done">
|
||||
<div class="task-icon task-icon--carrot">🥕</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">胡萝卜丁</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 2.5斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 11:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 周八</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--green" style="width: 100%"></div></div>
|
||||
<div class="progress-text">已包 2.5 / 需 2.5 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="task-action"><button class="action-btn action-btn--done">完成</button></div>
|
||||
</div>
|
||||
<!-- 任务项8 -->
|
||||
<div class="task-item" data-status="done">
|
||||
<div class="task-icon task-icon--cucumber">🥒</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">黄瓜条</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 3.0斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 11:30</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 刘九</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--green" style="width: 100%"></div></div>
|
||||
<div class="progress-text">已包 3.0 / 需 3.0 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="task-action"><button class="action-btn action-btn--done">完成</button></div>
|
||||
</div>
|
||||
<!-- 任务项9 -->
|
||||
<div class="task-item" data-status="done">
|
||||
<div class="task-icon task-icon--potato">🥔</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">土豆条</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 2.6斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 11:00</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 陈十</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--green" style="width: 100%"></div></div>
|
||||
<div class="progress-text">已包 2.6 / 需 2.6 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="task-action"><button class="action-btn action-btn--done">完成</button></div>
|
||||
</div>
|
||||
<!-- 任务项10 -->
|
||||
<div class="task-item" data-status="done">
|
||||
<div class="task-icon task-icon--tomato">🍅</div>
|
||||
<div class="task-info">
|
||||
<div class="task-name">小番茄</div>
|
||||
<div class="task-detail">
|
||||
<span class="task-detail__item">📦 总量: 1.8斤</span>
|
||||
<span class="task-detail__item">⏰ 截止: 14:30</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-target">👤 分配给: 杨一</div>
|
||||
<div class="task-progress">
|
||||
<div class="progress-bar"><div class="progress-bar__fill progress-bar__fill--green" style="width: 100%"></div></div>
|
||||
<div class="progress-text">已包 1.8 / 需 1.8 斤</div>
|
||||
</div>
|
||||
<div class="task-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="task-action"><button class="action-btn action-btn--done">完成</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 处理弹窗 -->
|
||||
<div class="modal-overlay" id="modalOverlay">
|
||||
<div class="modal-box">
|
||||
<div class="modal-header">
|
||||
<button class="modal-close" onclick="closeModal()">◀ 返回任务列表</button>
|
||||
<span class="modal-title" id="modalTitle">称重打包</span>
|
||||
<span style="width:80px"></span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-scale-panel">
|
||||
<div class="modal-task">
|
||||
<div class="modal-task__body">
|
||||
<div class="modal-task__icon task-icon--potato" id="modalTaskIcon">🥔</div>
|
||||
<div class="modal-task__info">
|
||||
<div class="modal-task__name" id="modalTaskName">土豆丝</div>
|
||||
<span class="modal-task__target" id="modalTaskTarget">👤 分配给: 张三</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-task__progress">
|
||||
<div class="progress-mini">
|
||||
<div class="progress-mini__fill" id="modalProgressFill" style="width:60%"></div>
|
||||
</div>
|
||||
<span class="progress-mini__text" id="modalProgressText">3.0/5.0斤</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scale-display" id="scaleDisplay">
|
||||
<div class="ai-result">
|
||||
<div class="ai-result__icon" id="aiIcon">📇</div>
|
||||
<div class="ai-result__info">
|
||||
<div class="ai-result__label">AI 识别结果</div>
|
||||
<div class="ai-result__name" id="aiName">等待放置食材...</div>
|
||||
<div class="ai-result__confidence" id="aiConfidence"></div>
|
||||
</div>
|
||||
<span class="ai-result__status ai-result__status--idle" id="aiStatus">待机</span>
|
||||
</div>
|
||||
<div class="weight-display">
|
||||
<span class="weight-display__value" id="weightValue">0.00</span>
|
||||
<span class="weight-display__unit">斤</span>
|
||||
<div class="weight-display__status" id="weightStatus">请将食材放置秤上</div>
|
||||
</div>
|
||||
<div class="scale-actions">
|
||||
<button class="scale-btn scale-btn--secondary" onclick="resetScale()">清零</button>
|
||||
<button class="scale-btn scale-btn--primary" id="packBtn" onclick="confirmPack()" disabled>打包+塑封</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-records-panel">
|
||||
<div class="modal-records">
|
||||
<div class="modal-records__header">
|
||||
<span class="modal-records__title">打包记录</span>
|
||||
<span class="modal-records__count" id="recordsCount">共 0 条</span>
|
||||
</div>
|
||||
<div class="modal-records__list" id="recordsList">
|
||||
<div class="modal-empty" id="emptyState">
|
||||
<div class="modal-empty__icon">📭</div>
|
||||
<div class="modal-empty__text">暂无打包记录</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toast" id="toast"></div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<script>
|
||||
/* 获取 URL 参数 */
|
||||
function getUrlParam(name) {
|
||||
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
|
||||
var r = window.location.search.substr(1).match(reg);
|
||||
@@ -421,201 +163,233 @@
|
||||
var userName = getUrlParam('user');
|
||||
if (userName) document.getElementById('topUser').textContent = '操作员: ' + userName;
|
||||
|
||||
// 筛选任务
|
||||
function filterTasks(status, tab) {
|
||||
document.querySelectorAll('.status-tab').forEach(function(el) {
|
||||
el.classList.remove('active--pending', 'active--done');
|
||||
});
|
||||
tab.classList.add(status === 'pending' ? 'active--pending' : 'active--done');
|
||||
document.querySelectorAll('.task-item').forEach(function(item) {
|
||||
item.style.display = (item.dataset.status === status) ? 'flex' : 'none';
|
||||
});
|
||||
}
|
||||
/* 当前 Tab 筛选 */
|
||||
var currentFilter = 'pending';
|
||||
|
||||
// ── 弹窗逻辑 ──
|
||||
var modalKey = '';
|
||||
var scaleState = 'idle';
|
||||
var currentWeight = 0;
|
||||
var currentAiResult = null;
|
||||
var records = [];
|
||||
|
||||
var taskData = {
|
||||
'potato': { name: '土豆丝', icon: '🥔', iconClass: 'task-icon--potato', need: 5.0, done: 3.0, target: '张三', deadline: '11:30' },
|
||||
'carrot': { name: '胡萝卜丝', icon: '🥕', iconClass: 'task-icon--carrot', need: 2.8, done: 0, target: '李四', deadline: '12:00' },
|
||||
'tomato': { name: '西红柿块', icon: '🍅', iconClass: 'task-icon--tomato', need: 3.5, done: 0, target: '孙七', deadline: '12:00' },
|
||||
'potato_dinner': { name: '土豆块(晚餐)', icon: '🥔', iconClass: 'task-icon--potato', need: 3.2, done: 1.0, target: '张三', deadline: '16:00' }
|
||||
};
|
||||
|
||||
var aiResults = {
|
||||
'potato': { name: '土豆丝', icon: '🥔', confidence: 97 },
|
||||
'tomato': { name: '西红柿块', icon: '🍅', confidence: 95 },
|
||||
'carrot': { name: '胡萝卜丝', icon: '🥕', confidence: 96 },
|
||||
'cucumber':{ name: '黄瓜片', icon: '🥒', confidence: 94 },
|
||||
'cabbage': { name: '白菜段', icon: '🥬', confidence: 93 }
|
||||
};
|
||||
|
||||
function openModal(key) {
|
||||
modalKey = key;
|
||||
var task = taskData[key] || taskData['potato'];
|
||||
var iconEl = document.getElementById('modalTaskIcon');
|
||||
iconEl.innerHTML = task.icon;
|
||||
iconEl.className = 'modal-task__icon ' + task.iconClass;
|
||||
document.getElementById('modalTaskName').textContent = task.name;
|
||||
document.getElementById('modalTaskTarget').innerHTML = '👤 分配给: ' + task.target;
|
||||
var pct = Math.round((task.done / task.need) * 100);
|
||||
document.getElementById('modalProgressFill').style.width = pct + '%';
|
||||
document.getElementById('modalProgressText').textContent = task.done.toFixed(1) + '/' + task.need.toFixed(1) + '斤';
|
||||
document.getElementById('modalTitle').textContent = task.name + ' - 称重打包';
|
||||
resetScale();
|
||||
records = [];
|
||||
updateRecordsDisplay();
|
||||
document.getElementById('modalOverlay').classList.add('open');
|
||||
setTimeout(function() { startDetecting(key.replace('_dinner','')); }, 1500);
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById('modalOverlay').classList.remove('open');
|
||||
}
|
||||
|
||||
function startDetecting(ingredientKey) {
|
||||
scaleState = 'detecting';
|
||||
var scale = document.getElementById('scaleDisplay');
|
||||
scale.classList.add('weighing');
|
||||
scale.classList.remove('stable');
|
||||
document.getElementById('weightStatus').textContent = '正在称重...';
|
||||
document.getElementById('weightStatus').className = 'weight-display__status weighing';
|
||||
var targetWeight = 2.05;
|
||||
var anim = 0;
|
||||
var timer = setInterval(function() {
|
||||
anim += 0.13;
|
||||
if (anim >= targetWeight) { anim = targetWeight; clearInterval(timer); onWeightStable(ingredientKey, targetWeight); }
|
||||
document.getElementById('weightValue').textContent = anim.toFixed(2);
|
||||
}, 100);
|
||||
setTimeout(function() {
|
||||
var result = aiResults[ingredientKey] || aiResults['potato'];
|
||||
currentAiResult = result;
|
||||
document.getElementById('aiIcon').innerHTML = result.icon;
|
||||
document.getElementById('aiName').textContent = result.name;
|
||||
document.getElementById('aiConfidence').textContent = '置信度: ' + result.confidence + '%';
|
||||
var task = taskData[modalKey];
|
||||
var isMatch = task.name === result.name || task.name.includes(result.name);
|
||||
var statusEl = document.getElementById('aiStatus');
|
||||
if (isMatch) {
|
||||
statusEl.textContent = '匹配';
|
||||
statusEl.className = 'ai-result__status ai-result__status--matching';
|
||||
} else {
|
||||
statusEl.textContent = '不匹配';
|
||||
statusEl.className = 'ai-result__status ai-result__status--mismatch';
|
||||
showToast('AI识别不匹配,请检查食材', 2500, 'error');
|
||||
/* 模拟数据:每任务只有1个餐品净菜包 */
|
||||
var mockData = [
|
||||
{
|
||||
orderNo: 'PO-20260616-001',
|
||||
expectedArrival: '11:30',
|
||||
taskNo: 'T-001',
|
||||
mealPack: {
|
||||
packName: '宫保鸡丁套餐',
|
||||
packSize: 3,
|
||||
notes: '少辣',
|
||||
ingredients: [
|
||||
{ name: '土豆丝', icon: '🥔', iconClass: 'child-icon--potato', weightPerPack: 500, weighed: 750 },
|
||||
{ name: '胡萝卜丝', icon: '🥕', iconClass: 'child-icon--carrot', weightPerPack: 500, weighed: 1500 },
|
||||
{ name: '黄瓜片', icon: '🥒', iconClass: 'child-icon--cucumber', weightPerPack: 500, weighed: 0 },
|
||||
{ name: '大葱丝', icon: '🧅', iconClass: 'child-icon--green-onion', weightPerPack: 500, weighed: 0 },
|
||||
{ name: '紫洋葱丝', icon: '🧅', iconClass: 'child-icon--onion', weightPerPack: 500, weighed: 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
orderNo: 'PO-20260616-002',
|
||||
expectedArrival: '12:00',
|
||||
taskNo: 'T-002',
|
||||
mealPack: {
|
||||
packName: '鱼香肉丝套餐',
|
||||
packSize: 2,
|
||||
notes: '',
|
||||
ingredients: [
|
||||
{ name: '胡萝卜丝', icon: '🥕', iconClass: 'child-icon--carrot', weightPerPack: 750, weighed: 0 },
|
||||
{ name: '白菜丝', icon: '🥬', iconClass: 'child-icon--cabbage', weightPerPack: 1000, weighed: 0 },
|
||||
{ name: '土豆丝', icon: '🥔', iconClass: 'child-icon--potato', weightPerPack: 500, weighed: 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
orderNo: 'PO-20260616-003',
|
||||
expectedArrival: '14:30',
|
||||
taskNo: 'T-003',
|
||||
mealPack: {
|
||||
packName: '番茄炒蛋套餐',
|
||||
packSize: 4,
|
||||
notes: '',
|
||||
ingredients: [
|
||||
{ name: '西红柿块', icon: '🍅', iconClass: 'child-icon--tomato', weightPerPack: 750, weighed: 3000 },
|
||||
{ name: '鸡蛋', icon: '🥚', iconClass: 'child-icon--egg', weightPerPack: 500, weighed: 2000 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
orderNo: 'PO-20260616-004',
|
||||
expectedArrival: '16:00',
|
||||
taskNo: 'T-004',
|
||||
mealPack: {
|
||||
packName: '凉拌黄瓜套餐',
|
||||
packSize: 5,
|
||||
notes: '多放蒜',
|
||||
ingredients: [
|
||||
{ name: '黄瓜条', icon: '🥒', iconClass: 'child-icon--cucumber', weightPerPack: 750, weighed: 3750 },
|
||||
{ name: '小番茄', icon: '🍅', iconClass: 'child-icon--tomato', weightPerPack: 250, weighed: 1250 }
|
||||
]
|
||||
}
|
||||
}, 800);
|
||||
}
|
||||
|
||||
function onWeightStable(key, weight) {
|
||||
scaleState = 'stable';
|
||||
currentWeight = weight;
|
||||
var scale = document.getElementById('scaleDisplay');
|
||||
scale.classList.remove('weighing');
|
||||
scale.classList.add('stable');
|
||||
document.getElementById('weightStatus').textContent = '重量已稳定';
|
||||
document.getElementById('weightStatus').className = 'weight-display__status stable';
|
||||
document.getElementById('packBtn').disabled = false;
|
||||
}
|
||||
|
||||
function confirmPack() {
|
||||
if (scaleState !== 'stable' || !currentAiResult) return;
|
||||
var task = taskData[modalKey];
|
||||
task.done += currentWeight;
|
||||
records.unshift({
|
||||
name: currentAiResult.name,
|
||||
icon: currentAiResult.icon,
|
||||
target: task.target,
|
||||
weight: currentWeight,
|
||||
time: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
|
||||
});
|
||||
updateRecordsDisplay();
|
||||
var pct = Math.round((task.done / task.need) * 100);
|
||||
document.getElementById('modalProgressFill').style.width = pct + '%';
|
||||
document.getElementById('modalProgressText').textContent = task.done.toFixed(1) + '/' + task.need.toFixed(1) + '斤';
|
||||
showToast('打包成功: ' + currentAiResult.name + ' ' + currentWeight.toFixed(2) + '斤 → ' + task.target, 2500, 'success');
|
||||
resetScale();
|
||||
}
|
||||
|
||||
function updateRecordsDisplay() {
|
||||
var list = document.getElementById('recordsList');
|
||||
var empty = document.getElementById('emptyState');
|
||||
if (records.length === 0) {
|
||||
empty.style.display = 'flex';
|
||||
document.getElementById('recordsCount').textContent = '共 0 条';
|
||||
return;
|
||||
}
|
||||
empty.style.display = 'none';
|
||||
document.getElementById('recordsCount').textContent = '共 ' + records.length + ' 条';
|
||||
var existing = list.querySelectorAll('.modal-record');
|
||||
existing.forEach(function(el) { el.remove(); });
|
||||
records.forEach(function(r) {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'modal-record';
|
||||
item.innerHTML = '<div class="modal-record__icon">' + r.icon + '</div>' +
|
||||
'<div class="modal-record__info"><div class="modal-record__name">' + r.name + '</div>' +
|
||||
'<div class="modal-record__target">→ ' + r.target + '</div>' +
|
||||
'<div class="modal-record__time">' + r.time + '</div></div>' +
|
||||
'<div class="modal-record__weight">+' + r.weight.toFixed(2) + '斤</div>' +
|
||||
'<div class="modal-record__seal">🔒 已塑封</div>';
|
||||
list.appendChild(item);
|
||||
];
|
||||
|
||||
/* 获取餐品净菜包状态 */
|
||||
function getPackStatus(pack) {
|
||||
var allDone = pack.ingredients.every(function(ing) {
|
||||
return ing.weighed >= ing.weightPerPack * pack.packSize;
|
||||
});
|
||||
if (allDone) return { text: '已完成', cls: 'status-badge--done' };
|
||||
return { text: '待称重', cls: 'status-badge--pending' };
|
||||
}
|
||||
|
||||
/* 判断餐品净菜包是否有待称重项 */
|
||||
function hasPendingPack(pack) {
|
||||
return pack.ingredients.some(function(ing) {
|
||||
return ing.weighed < ing.weightPerPack * pack.packSize;
|
||||
});
|
||||
}
|
||||
|
||||
function resetScale() {
|
||||
scaleState = 'idle';
|
||||
currentWeight = 0;
|
||||
currentAiResult = null;
|
||||
var scale = document.getElementById('scaleDisplay');
|
||||
scale.classList.remove('weighing', 'stable');
|
||||
document.getElementById('weightValue').textContent = '0.00';
|
||||
document.getElementById('weightStatus').textContent = '请将食材放置秤上';
|
||||
document.getElementById('weightStatus').className = 'weight-display__status';
|
||||
document.getElementById('aiIcon').innerHTML = '📇';
|
||||
document.getElementById('aiName').textContent = '等待放置食材...';
|
||||
document.getElementById('aiConfidence').textContent = '';
|
||||
document.getElementById('aiStatus').textContent = '待机';
|
||||
document.getElementById('aiStatus').className = 'ai-result__status ai-result__status--idle';
|
||||
document.getElementById('packBtn').disabled = true;
|
||||
setTimeout(function() {
|
||||
if (scaleState === 'idle' && document.getElementById('modalOverlay').classList.contains('open')) {
|
||||
var keys = ['potato', 'carrot', 'cucumber'];
|
||||
startDetecting(keys[Math.floor(Math.random() * keys.length)]);
|
||||
}
|
||||
}, 3000);
|
||||
/* 渲染任务列表 */
|
||||
function renderTaskList() {
|
||||
var container = document.getElementById('taskListContainer');
|
||||
container.innerHTML = '';
|
||||
|
||||
var pendingCount = 0;
|
||||
var doneCount = 0;
|
||||
|
||||
mockData.forEach(function(order) {
|
||||
var pack = order.mealPack;
|
||||
var hasPending = hasPendingPack(pack);
|
||||
if (hasPending) pendingCount++; else doneCount++;
|
||||
|
||||
var taskCard = document.createElement('div');
|
||||
taskCard.className = 'task-card';
|
||||
|
||||
/* 合并行:订单号 + 任务号 + 期望到货 + 状态 + 去称重 */
|
||||
var header = document.createElement('div');
|
||||
header.className = 'task-card__header';
|
||||
header.innerHTML =
|
||||
'<span class="task-card__order-info"><span class="task-card__order-info__label">订单号:</span><span class="task-card__order-info__value">' + order.orderNo + '</span></span>' +
|
||||
'<span class="task-card__order-info"><span class="task-card__order-info__label">任务号:</span><span class="task-card__order-info__value">' + order.taskNo + '</span></span>' +
|
||||
'<span class="task-card__arrival">⏰ 期望到货:<span class="task-card__arrival__time">' + order.expectedArrival + '</span></span>' +
|
||||
'<span class="task-card__status"><span class="status-badge ' + (hasPending ? 'status-badge--pending' : 'status-badge--done') + '">' + (hasPending ? '待称重' : '已完成') + '</span></span>' +
|
||||
(hasPending
|
||||
? '<button class="task-card__pack-btn" onclick="handleWeigh(\'' + order.taskNo + '\',\'' + order.orderNo + '\',\'' + pack.packName + '\')">去称重</button>'
|
||||
: '<button class="task-card__pack-btn" disabled>全部完成</button>');
|
||||
taskCard.appendChild(header);
|
||||
|
||||
/* 表格头(6列) */
|
||||
var tableHead = document.createElement('div');
|
||||
tableHead.className = 'item-table__head';
|
||||
tableHead.innerHTML = '<div>名称</div><div style="text-align:center">每份用量</div><div style="text-align:center">打包规格</div><div style="text-align:right">所需总重</div><div style="text-align:right">已称</div><div style="text-align:center">状态</div>';
|
||||
taskCard.appendChild(tableHead);
|
||||
|
||||
/* 表格体 */
|
||||
var tableBody = document.createElement('div');
|
||||
tableBody.className = 'item-table__body';
|
||||
|
||||
var packStatus = getPackStatus(pack);
|
||||
var totalNeed = 0;
|
||||
var totalWeighed = 0;
|
||||
pack.ingredients.forEach(function(ing) {
|
||||
totalNeed += ing.weightPerPack * pack.packSize;
|
||||
totalWeighed += ing.weighed;
|
||||
});
|
||||
totalNeed = Math.round(totalNeed * 100) / 100;
|
||||
totalWeighed = Math.round(totalWeighed * 100) / 100;
|
||||
var weightClass = totalWeighed >= totalNeed ? 'parent-weight--done' : '';
|
||||
|
||||
/* 主行:餐品净菜包 */
|
||||
var parentRow = document.createElement('div');
|
||||
parentRow.className = 'item-parent-row';
|
||||
parentRow.innerHTML =
|
||||
'<div class="parent-name"><div class="parent-icon">📦</div><span class="parent-name__text">' + pack.packName + '</span></div>' +
|
||||
'<div style="text-align:center;font-size:12px;color:rgba(255,255,255,0.5)">—</div>' +
|
||||
'<div style="text-align:center"><span class="pack-size-tag">' + pack.packSize + ' 份</span></div>' +
|
||||
'<div class="parent-weight ' + weightClass + '">需 ' + totalNeed + ' 克</div>' +
|
||||
'<div class="parent-weight ' + weightClass + '">已 ' + totalWeighed + ' 克</div>' +
|
||||
'<div style="text-align:center"><span class="status-tag ' + (packStatus.text === '已完成' ? 'status-tag--done' : 'status-tag--wait') + '">' + packStatus.text + '</span></div>';
|
||||
tableBody.appendChild(parentRow);
|
||||
|
||||
/* 子行:每种食材 */
|
||||
pack.ingredients.forEach(function(ing) {
|
||||
var need = Math.round(ing.weightPerPack * pack.packSize * 100) / 100;
|
||||
var isDone = ing.weighed >= need;
|
||||
var childWeightClass = isDone ? 'child-weight--done' : '';
|
||||
|
||||
var childRow = document.createElement('div');
|
||||
childRow.className = 'item-child-row';
|
||||
childRow.innerHTML =
|
||||
'<div class="child-name"><div class="child-icon ' + ing.iconClass + '">' + ing.icon + '</div><span class="child-name__text">' + ing.name + '</span></div>' +
|
||||
'<div class="child-weight" style="text-align:center">' + ing.weightPerPack + ' 克</div>' +
|
||||
'<div class="child-pack-size">×</div>' +
|
||||
'<div class="child-weight" style="text-align:right">' + need + ' 克</div>' +
|
||||
'<div class="child-weight ' + childWeightClass + '" style="text-align:right">' + ing.weighed + ' 克</div>' +
|
||||
'<div style="text-align:center"><span class="status-tag ' + (isDone ? 'status-tag--done' : 'status-tag--wait') + '">' + (isDone ? '已完成' : '待称重') + '</span></div>';
|
||||
tableBody.appendChild(childRow);
|
||||
});
|
||||
|
||||
taskCard.appendChild(tableBody);
|
||||
container.appendChild(taskCard);
|
||||
});
|
||||
|
||||
/* 更新 Tab 计数 */
|
||||
document.getElementById('pendingCount').textContent = pendingCount;
|
||||
document.getElementById('doneCount').textContent = doneCount;
|
||||
}
|
||||
|
||||
/* 切换 Tab */
|
||||
function switchTab(filter, el) {
|
||||
currentFilter = filter;
|
||||
document.querySelectorAll('.tab').forEach(function(tab) { tab.classList.remove('active'); });
|
||||
el.classList.add('active');
|
||||
|
||||
document.querySelectorAll('.task-card').forEach(function(card) {
|
||||
var packBtn = card.querySelector('.task-card__pack-btn');
|
||||
var hasPending = packBtn && !packBtn.disabled;
|
||||
if (filter === 'pending') {
|
||||
card.style.display = hasPending ? 'block' : 'none';
|
||||
} else {
|
||||
card.style.display = hasPending ? 'none' : 'block';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* 去称重 */
|
||||
function handleWeigh(taskNo, orderNo, packName) {
|
||||
var target = '02-weighing-packing.html?task=' + taskNo + '&pack=' + encodeURIComponent(packName) + '&order=' + encodeURIComponent(orderNo);
|
||||
if (userName) target += '&user=' + encodeURIComponent(userName);
|
||||
window.location.href = target;
|
||||
}
|
||||
|
||||
/* Toast 提示 */
|
||||
function showToast(msg, duration, type) {
|
||||
var el = document.getElementById('toast');
|
||||
el.textContent = msg;
|
||||
el.className = 'toast';
|
||||
if (type === 'error') el.classList.add('toast--error');
|
||||
if (type === 'success') el.classList.add('toast--success');
|
||||
if (type === 'warn') el.classList.add('toast--warn');
|
||||
el.classList.add('show');
|
||||
clearTimeout(el._timer);
|
||||
el._timer = setTimeout(function() { el.classList.remove('show'); }, duration || 2000);
|
||||
}
|
||||
|
||||
/* 初始化 */
|
||||
renderTaskList();
|
||||
/* 初始过滤:待称重 Tab 默认不显示已完成订单 */
|
||||
switchTab('pending', document.querySelector('.tab[data-filter="pending"]'));
|
||||
|
||||
/* 返回按钮 */
|
||||
(function() {
|
||||
var backBtn = document.getElementById('backBtn');
|
||||
if (backBtn) {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var referer = params.get('referer');
|
||||
if (referer) {
|
||||
backBtn.href = referer;
|
||||
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
|
||||
backBtn.href = document.referrer;
|
||||
} else {
|
||||
backBtn.href = '00-welcome.html';
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
/* 返回按钮:从哪来回哪去 */
|
||||
(function() {
|
||||
var backBtn = document.getElementById('backBtn');
|
||||
if (backBtn) {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var referer = params.get('referer');
|
||||
if (referer) {
|
||||
backBtn.href = referer;
|
||||
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
|
||||
backBtn.href = document.referrer;
|
||||
} else {
|
||||
backBtn.href = 'index.html';
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,258 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1280, initial-scale=1.0">
|
||||
<title>净菜配比秤 - 打包记录 | 蚁熊智能餐养平台</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden; }
|
||||
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
|
||||
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
|
||||
.back-btn:hover { color: #fff; }
|
||||
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
|
||||
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
|
||||
.main-content { height: calc(100% - 44px); padding: 20px 28px; display: flex; flex-direction: column; gap: 16px; }
|
||||
.filter-bar { display: flex; align-items: center; gap: 12px; }
|
||||
.filter-group { display: flex; align-items: center; gap: 8px; }
|
||||
.filter-label { font-size: 12px; color: rgba(255,255,255,0.5); }
|
||||
.filter-select { background: #1a2b4a; border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 8px 12px; font-size: 12px; color: #fff; outline: none; cursor: pointer; }
|
||||
.filter-input { background: #1a2b4a; border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 8px 12px; font-size: 12px; color: #fff; outline: none; width: 140px; }
|
||||
.filter-btn { padding: 8px 16px; border-radius: 6px; font-size: 12px; background: #4a90d9; color: #fff; border: none; cursor: pointer; }
|
||||
.filter-btn:hover { background: #5ba0e9; }
|
||||
.filter-btn--secondary { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.8); }
|
||||
.filter-btn--secondary:hover { background: rgba(255,255,255,0.12); }
|
||||
.stats-row { display: flex; gap: 14px; }
|
||||
.stat-card { flex: 1; background: #1a2b4a; border-radius: 12px; padding: 16px 20px; border: 1px solid rgba(255,255,255,0.06); }
|
||||
.stat-card__label { font-size: 12px; color: rgba(255,255,255,0.5); margin-bottom: 6px; }
|
||||
.stat-card__value { font-size: 24px; font-weight: 700; color: #fff; }
|
||||
.stat-card__value--green { color: #52c41a; }
|
||||
.stat-card__value--blue { color: #4a90d9; }
|
||||
.records-section { flex: 1; background: #1a2b4a; border-radius: 12px; padding: 16px 20px; display: flex; flex-direction: column; overflow: hidden; }
|
||||
.records-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
|
||||
.records-title { font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.8); }
|
||||
.records-count { font-size: 12px; color: rgba(255,255,255,0.4); }
|
||||
.table-header { display: flex; align-items: center; padding: 10px 16px; background: rgba(0,0,0,0.2); border-radius: 8px; margin-bottom: 8px; }
|
||||
.table-header__cell { font-size: 12px; color: rgba(255,255,255,0.5); font-weight: 500; }
|
||||
.col-batch { flex: 0 0 130px; }
|
||||
.col-name { flex: 0 0 100px; }
|
||||
.col-target { flex: 0 0 80px; }
|
||||
.col-weight { flex: 0 0 80px; }
|
||||
.col-time { flex: 0 0 80px; }
|
||||
.col-seal { flex: 0 0 80px; }
|
||||
.col-operator { flex: 0 0 80px; }
|
||||
.col-status { flex: 0 0 80px; }
|
||||
.col-action { flex: 1; text-align: right; }
|
||||
.records-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.1) transparent; }
|
||||
.records-list::-webkit-scrollbar { width: 4px; }
|
||||
.records-list::-webkit-scrollbar-track { background: transparent; }
|
||||
.records-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
|
||||
.record-row { display: flex; align-items: center; padding: 12px 16px; background: rgba(0,0,0,0.15); border-radius: 8px; transition: background 0.2s; }
|
||||
.record-row:hover { background: rgba(74,144,217,0.08); }
|
||||
.record-row__cell { font-size: 13px; color: rgba(255,255,255,0.8); }
|
||||
.record-row__cell--icon { font-size: 18px; }
|
||||
.seal-badge { display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 11px; background: rgba(74,144,217,0.15); color: #4a90d9; }
|
||||
.status-badge { display: inline-block; padding: 3px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; }
|
||||
.status-badge--done { background: rgba(82,196,26,0.15); color: #52c41a; }
|
||||
.action-link { font-size: 12px; color: #4a90d9; cursor: pointer; text-decoration: none; }
|
||||
.action-link:hover { text-decoration: underline; }
|
||||
.pagination { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,0.06); }
|
||||
.pagination__info { font-size: 12px; color: rgba(255,255,255,0.4); margin-right: auto; }
|
||||
.pagination__btn { width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.6); font-size: 12px; border: none; cursor: pointer; transition: all 0.2s; }
|
||||
.pagination__btn:hover { background: rgba(255,255,255,0.1); color: #fff; }
|
||||
.pagination__btn.active { background: #4a90d9; color: #fff; }
|
||||
.pagination__btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
|
||||
<a class="back-btn" id="backBtn" href="javascript:void(0)">◀ 返回</a> <span class="top-bar__title">打包记录</span>
|
||||
<span class="top-bar__user" id="topUser">--</span>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div class="filter-bar">
|
||||
<div class="filter-group"><span class="filter-label">日期</span><input type="date" class="filter-input" value="2026-06-13"></div>
|
||||
<div class="filter-group">
|
||||
<span class="filter-label">食材</span>
|
||||
<select class="filter-select"><option value="">全部</option><option value="potato">土豆丝</option><option value="carrot">胡萝卜丝</option><option value="cucumber">黄瓜片</option><option value="cabbage">白菜段</option><option value="tomato">西红柿块</option></select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<span class="filter-label">目标员工</span>
|
||||
<select class="filter-select"><option value="">全部</option><option>张三</option><option>李四</option><option>王五</option><option>赵六</option><option>孙七</option></select>
|
||||
</div>
|
||||
<button class="filter-btn">查询</button>
|
||||
<button class="filter-btn filter-btn--secondary">重置</button>
|
||||
</div>
|
||||
<div class="stats-row">
|
||||
<div class="stat-card"><div class="stat-card__label">今日打包批次</div><div class="stat-card__value stat-card__value--blue">15</div></div>
|
||||
<div class="stat-card"><div class="stat-card__label">打包总量</div><div class="stat-card__value">48.6斤</div></div>
|
||||
<div class="stat-card"><div class="stat-card__label">分配员工数</div><div class="stat-card__value">8</div></div>
|
||||
<div class="stat-card"><div class="stat-card__label">塑封完成率</div><div class="stat-card__value stat-card__value--green">100%</div></div>
|
||||
</div>
|
||||
<div class="records-section">
|
||||
<div class="records-header">
|
||||
<span class="records-title">打包记录列表</span>
|
||||
<span class="records-count">共 15 条记录</span>
|
||||
</div>
|
||||
<div class="table-header">
|
||||
<div class="table-header__cell col-batch">批次号</div>
|
||||
<div class="table-header__cell col-name">食材</div>
|
||||
<div class="table-header__cell col-target">目标员工</div>
|
||||
<div class="table-header__cell col-weight">重量</div>
|
||||
<div class="table-header__cell col-time">打包时间</div>
|
||||
<div class="table-header__cell col-seal">塑封</div>
|
||||
<div class="table-header__cell col-operator">操作员</div>
|
||||
<div class="table-header__cell col-status">状态</div>
|
||||
<div class="table-header__cell col-action">操作</div>
|
||||
</div>
|
||||
<div class="records-list">
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-001</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥔</span> 土豆丝</div>
|
||||
<div class="record-row__cell col-target">张三</div>
|
||||
<div class="record-row__cell col-weight">5.2斤</div>
|
||||
<div class="record-row__cell col-time">09:45</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-002</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥕</span> 胡萝卜丝</div>
|
||||
<div class="record-row__cell col-target">李四</div>
|
||||
<div class="record-row__cell col-weight">2.8斤</div>
|
||||
<div class="record-row__cell col-time">09:58</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-003</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥒</span> 黄瓜片</div>
|
||||
<div class="record-row__cell col-target">王五</div>
|
||||
<div class="record-row__cell col-weight">4.2斤</div>
|
||||
<div class="record-row__cell col-time">10:12</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-004</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥬</span> 白菜段</div>
|
||||
<div class="record-row__cell col-target">赵六</div>
|
||||
<div class="record-row__cell col-weight">8.5斤</div>
|
||||
<div class="record-row__cell col-time">10:28</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-005</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🍅</span> 西红柿块</div>
|
||||
<div class="record-row__cell col-target">孙七</div>
|
||||
<div class="record-row__cell col-weight">3.5斤</div>
|
||||
<div class="record-row__cell col-time">10:42</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-006</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥔</span> 土豆丝</div>
|
||||
<div class="record-row__cell col-target">周八</div>
|
||||
<div class="record-row__cell col-weight">3.0斤</div>
|
||||
<div class="record-row__cell col-time">10:55</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-007</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥔</span> 土豆块</div>
|
||||
<div class="record-row__cell col-target">张三</div>
|
||||
<div class="record-row__cell col-weight">3.2斤</div>
|
||||
<div class="record-row__cell col-time">14:30</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-008</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥕</span> 胡萝卜丁</div>
|
||||
<div class="record-row__cell col-target">陈十</div>
|
||||
<div class="record-row__cell col-weight">2.5斤</div>
|
||||
<div class="record-row__cell col-time">14:45</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-009</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🥔</span> 土豆条</div>
|
||||
<div class="record-row__cell col-target">刘九</div>
|
||||
<div class="record-row__cell col-weight">2.6斤</div>
|
||||
<div class="record-row__cell col-time">14:58</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
<div class="record-row">
|
||||
<div class="record-row__cell col-batch">#P20260613-010</div>
|
||||
<div class="record-row__cell col-name"><span class="record-row__cell--icon">🍅</span> 小番茄</div>
|
||||
<div class="record-row__cell col-target">杨一</div>
|
||||
<div class="record-row__cell col-weight">1.8斤</div>
|
||||
<div class="record-row__cell col-time">15:10</div>
|
||||
<div class="record-row__cell col-seal"><span class="seal-badge">🔒 已塑封</span></div>
|
||||
<div class="record-row__cell col-operator">刘九</div>
|
||||
<div class="record-row__cell col-status"><span class="status-badge status-badge--done">已完成</span></div>
|
||||
<div class="record-row__cell col-action"><a class="action-link">查看详情</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<span class="pagination__info">共 15 条,第 1/2 页</span>
|
||||
<button class="pagination__btn" disabled>‹</button>
|
||||
<button class="pagination__btn active">1</button>
|
||||
<button class="pagination__btn">2</button>
|
||||
<button class="pagination__btn">›</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function getUrlParam(name) {
|
||||
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
|
||||
var r = window.location.search.substr(1).match(reg);
|
||||
if (r !== null) return decodeURIComponent(r[2]);
|
||||
return null;
|
||||
}
|
||||
var userName = getUrlParam('user');
|
||||
if (userName) document.getElementById('topUser').textContent = '操作员: ' + userName;
|
||||
</script>
|
||||
|
||||
/* 返回按钮:从哪来回哪去 */
|
||||
(function() {
|
||||
var backBtn = document.getElementById('backBtn');
|
||||
if (backBtn) {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var referer = params.get('referer');
|
||||
if (referer) {
|
||||
backBtn.href = referer;
|
||||
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
|
||||
backBtn.href = document.referrer;
|
||||
} else {
|
||||
backBtn.href = 'index.html';
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,189 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1280, initial-scale=1.0">
|
||||
<title>净菜配比秤 - 设备设置 | 蚁熊智能餐养平台</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden; }
|
||||
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
|
||||
.back-btn { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; transition: color 0.2s; }
|
||||
.back-btn:hover { color: #fff; }
|
||||
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
|
||||
.top-bar__user { font-size: 12px; color: rgba(255,255,255,0.5); }
|
||||
.main-content { height: calc(100% - 44px); padding: 24px 32px; display: flex; gap: 24px; }
|
||||
.settings-menu { flex: 0 0 200px; background: #1a2b4a; border-radius: 12px; padding: 12px; display: flex; flex-direction: column; gap: 4px; }
|
||||
.menu-item { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-radius: 8px; cursor: pointer; font-size: 13px; color: rgba(255,255,255,0.6); transition: all 0.2s; }
|
||||
.menu-item:hover { background: rgba(255,255,255,0.06); color: #fff; }
|
||||
.menu-item.active { background: rgba(74,144,217,0.15); color: #4a90d9; }
|
||||
.menu-item__icon { font-size: 16px; }
|
||||
.settings-content { flex: 1; background: #1a2b4a; border-radius: 12px; padding: 24px 28px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.1) transparent; }
|
||||
.settings-content::-webkit-scrollbar { width: 4px; }
|
||||
.settings-content::-webkit-scrollbar-track { background: transparent; }
|
||||
.settings-content::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 2px; }
|
||||
.settings-section { margin-bottom: 28px; }
|
||||
.settings-section:last-child { margin-bottom: 0; }
|
||||
.section-title { font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.8); padding-bottom: 12px; border-bottom: 1px solid rgba(255,255,255,0.08); margin-bottom: 16px; }
|
||||
.setting-item { display: flex; align-items: center; padding: 14px 0; border-bottom: 1px solid rgba(255,255,255,0.04); }
|
||||
.setting-item:last-child { border-bottom: none; }
|
||||
.setting-item__info { flex: 1; }
|
||||
.setting-item__label { font-size: 13px; color: rgba(255,255,255,0.8); margin-bottom: 2px; }
|
||||
.setting-item__desc { font-size: 11px; color: rgba(255,255,255,0.4); }
|
||||
.setting-item__control { flex: 0 0 auto; }
|
||||
.setting-input { background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 8px 12px; font-size: 13px; color: #fff; outline: none; width: 120px; text-align: right; }
|
||||
.setting-input:focus { border-color: #4a90d9; }
|
||||
.setting-select { background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; padding: 8px 12px; font-size: 13px; color: #fff; outline: none; cursor: pointer; }
|
||||
.toggle { width: 44px; height: 24px; border-radius: 12px; background: rgba(255,255,255,0.15); position: relative; cursor: pointer; transition: background 0.2s; }
|
||||
.toggle.on { background: #4a90d9; }
|
||||
.toggle__knob { width: 20px; height: 20px; border-radius: 50%; background: #fff; position: absolute; top: 2px; left: 2px; transition: left 0.2s; }
|
||||
.toggle.on .toggle__knob { left: 22px; }
|
||||
.device-info { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
||||
.info-item { background: rgba(0,0,0,0.15); border-radius: 10px; padding: 14px 16px; }
|
||||
.info-item__label { font-size: 11px; color: rgba(255,255,255,0.4); margin-bottom: 4px; }
|
||||
.info-item__value { font-size: 14px; color: #fff; font-weight: 500; }
|
||||
.info-item__value--online { color: #52c41a; }
|
||||
.save-btn { display: block; width: 100%; padding: 14px; border-radius: 10px; background: #4a90d9; color: #fff; font-size: 14px; font-weight: 600; border: none; cursor: pointer; transition: all 0.2s; margin-top: 24px; }
|
||||
.save-btn:hover { background: #5ba0e9; }
|
||||
.toast { position: fixed; top: 60px; left: 50%; transform: translateX(-50%) translateY(-20px); background: rgba(0,0,0,0.85); color: #fff; padding: 12px 28px; border-radius: 8px; font-size: 13px; z-index: 1000; opacity: 0; visibility: hidden; transition: opacity 0.3s, transform 0.3s, visibility 0.3s; white-space: nowrap; pointer-events: none; }
|
||||
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
|
||||
.toast--success { background: rgba(82,196,26,0.92); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
|
||||
<a class="back-btn" id="backBtn" href="javascript:void(0)">◀ 返回</a> <span class="top-bar__title">设备设置</span>
|
||||
<span class="top-bar__user" id="topUser">--</span>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div class="settings-menu">
|
||||
<div class="menu-item active" onclick="switchSection('packing', this)"><span class="menu-item__icon">📦</span><span>打包参数</span></div>
|
||||
<div class="menu-item" onclick="switchSection('ai', this)"><span class="menu-item__icon">🤖</span><span>AI识别</span></div>
|
||||
<div class="menu-item" onclick="switchSection('scale', this)"><span class="menu-item__icon">⚖️</span><span>秤参数</span></div>
|
||||
<div class="menu-item" onclick="switchSection('device', this)"><span class="menu-item__icon">💻</span><span>设备信息</span></div>
|
||||
<div class="menu-item" onclick="switchSection('about', this)"><span class="menu-item__icon">ℹ️</span><span>关于</span></div>
|
||||
</div>
|
||||
<div class="settings-content">
|
||||
<div class="settings-section" id="section-packing">
|
||||
<div class="section-title">打包参数配置</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">自动塑封</div><div class="setting-item__desc">打包完成后自动塑封</div></div>
|
||||
<div class="setting-item__control"><div class="toggle on" onclick="toggleSwitch(this)"><div class="toggle__knob"></div></div></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">标签打印</div><div class="setting-item__desc">打包完成后自动打印标签</div></div>
|
||||
<div class="setting-item__control"><div class="toggle on" onclick="toggleSwitch(this)"><div class="toggle__knob"></div></div></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">重量误差范围</div><div class="setting-item__desc">打包重量与目标重量的允许误差</div></div>
|
||||
<div class="setting-item__control"><input type="number" class="setting-input" value="0.2" min="0.1" max="1" step="0.1"> <span style="color: rgba(255,255,255,0.5); font-size: 12px; margin-left: 4px">斤</span></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">打包完成提示音</div><div class="setting-item__desc">打包完成时播放提示音</div></div>
|
||||
<div class="setting-item__control"><div class="toggle on" onclick="toggleSwitch(this)"><div class="toggle__knob"></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-section" id="section-ai" style="display:none">
|
||||
<div class="section-title">AI 识别设置</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">识别置信度阈值</div><div class="setting-item__desc">低于此值将提示人工确认</div></div>
|
||||
<div class="setting-item__control"><input type="number" class="setting-input" value="85" min="60" max="99"> <span style="color: rgba(255,255,255,0.5); font-size: 12px; margin-left: 4px">%</span></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">不匹配自动告警</div><div class="setting-item__desc">AI识别与任务不匹配时弹窗提示</div></div>
|
||||
<div class="setting-item__control"><div class="toggle on" onclick="toggleSwitch(this)"><div class="toggle__knob"></div></div></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">连续识别模式</div><div class="setting-item__desc">放置食材后自动触发识别</div></div>
|
||||
<div class="setting-item__control"><div class="toggle on" onclick="toggleSwitch(this)"><div class="toggle__knob"></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-section" id="section-scale" style="display:none">
|
||||
<div class="section-title">秤参数配置</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">重量单位</div><div class="setting-item__desc">称重显示单位</div></div>
|
||||
<div class="setting-item__control"><select class="setting-select"><option selected>斤</option><option>克</option><option>千克</option></select></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">小数位数</div><div class="setting-item__desc">重量显示精度</div></div>
|
||||
<div class="setting-item__control"><select class="setting-select"><option>1位</option><option selected>2位</option></select></div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-item__info"><div class="setting-item__label">稳定判定时间</div><div class="setting-item__desc">重量稳定后自动锁定的等待时间</div></div>
|
||||
<div class="setting-item__control"><input type="number" class="setting-input" value="3" min="1" max="10"> <span style="color: rgba(255,255,255,0.5); font-size: 12px; margin-left: 4px">秒</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-section" id="section-device" style="display:none">
|
||||
<div class="section-title">设备信息</div>
|
||||
<div class="device-info">
|
||||
<div class="info-item"><div class="info-item__label">设备名称</div><div class="info-item__value">净菜配比秤-01</div></div>
|
||||
<div class="info-item"><div class="info-item__label">设备编号</div><div class="info-item__value">JC PB-2026-001</div></div>
|
||||
<div class="info-item"><div class="info-item__label">固件版本</div><div class="info-item__value">v2.3.1</div></div>
|
||||
<div class="info-item"><div class="info-item__label">AI模型版本</div><div class="info-item__value">pack-ai-v2.5</div></div>
|
||||
<div class="info-item"><div class="info-item__label">设备状态</div><div class="info-item__value info-item__value--online">在线</div></div>
|
||||
<div class="info-item"><div class="info-item__label">网络状态</div><div class="info-item__value info-item__value--online">已连接</div></div>
|
||||
<div class="info-item"><div class="info-item__label">上次校准</div><div class="info-item__value">2026-06-10</div></div>
|
||||
<div class="info-item"><div class="info-item__label">累计使用</div><div class="info-item__value">128天</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-section" id="section-about" style="display:none">
|
||||
<div class="section-title">关于</div>
|
||||
<div class="device-info">
|
||||
<div class="info-item"><div class="info-item__label">系统名称</div><div class="info-item__value">蚁熊智能餐养平台</div></div>
|
||||
<div class="info-item"><div class="info-item__label">系统版本</div><div class="info-item__value">v5.8.0</div></div>
|
||||
<div class="info-item"><div class="info-item__label">设备类型</div><div class="info-item__value">净菜配比秤</div></div>
|
||||
<div class="info-item"><div class="info-item__label">制造商</div><div class="info-item__value">蚁熊智能科技有限公司</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="save-btn" onclick="saveSettings()">保存设置</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toast" id="toast"></div>
|
||||
<script>
|
||||
function getUrlParam(name) {
|
||||
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
|
||||
var r = window.location.search.substr(1).match(reg);
|
||||
if (r !== null) return decodeURIComponent(r[2]);
|
||||
return null;
|
||||
}
|
||||
var userName = getUrlParam('user');
|
||||
if (userName) document.getElementById('topUser').textContent = '操作员: ' + userName;
|
||||
|
||||
function switchSection(section, el) {
|
||||
document.querySelectorAll('.menu-item').forEach(function(item) { item.classList.remove('active'); });
|
||||
el.classList.add('active');
|
||||
document.querySelectorAll('.settings-section').forEach(function(sec) { sec.style.display = 'none'; });
|
||||
document.getElementById('section-' + section).style.display = 'block';
|
||||
}
|
||||
function toggleSwitch(el) { el.classList.toggle('on'); }
|
||||
function saveSettings() { showToast('设置已保存', 2000, 'success'); }
|
||||
function showToast(msg, duration, type) {
|
||||
var el = document.getElementById('toast');
|
||||
el.textContent = msg;
|
||||
el.className = 'toast';
|
||||
if (type === 'success') el.classList.add('toast--success');
|
||||
el.classList.add('show');
|
||||
clearTimeout(el._timer);
|
||||
el._timer = setTimeout(function() { el.classList.remove('show'); }, duration || 2000);
|
||||
}
|
||||
</script>
|
||||
|
||||
/* 返回按钮:从哪来回哪去 */
|
||||
(function() {
|
||||
var backBtn = document.getElementById('backBtn');
|
||||
if (backBtn) {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var referer = params.get('referer');
|
||||
if (referer) {
|
||||
backBtn.href = referer;
|
||||
} else if (document.referrer && document.referrer.indexOf(window.location.hostname) !== -1) {
|
||||
backBtn.href = document.referrer;
|
||||
} else {
|
||||
backBtn.href = 'index.html';
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,43 @@
|
||||
# 净菜配比秤 CHANGELOG
|
||||
|
||||
## [1.2.0] - 2026-06-16
|
||||
|
||||
### 新增
|
||||
- 称重打包页食材识别区底部新增「当前秤重」实时显示
|
||||
- 净菜清清单表格新增「操作」列,支持单独清空食材重量
|
||||
- 称重打包页新增「下一步」按钮,点击后弹出包装信息窗口
|
||||
- 包装信息弹窗包含:包装方式(必填)、保质期至(必填/三列下拉)、存放温度、终端设备(下拉)
|
||||
|
||||
### 调整
|
||||
- 表头列名优化:「每份用量」→「每份用量(克)」、「打包规格」→「打包规格(份)」
|
||||
- 称重打包页删除「保存并完成」「保存并继续」按钮,统一改为「下一步」弹窗流程
|
||||
- 全局去除「今日」字样:标题、导航、卡片描述统一精简
|
||||
- 保质期至由浏览器原生日期控件改为自定义三列下拉(年/月/日)
|
||||
|
||||
### 修复
|
||||
- 任务列表页「待称重」Tab 初始化时未过滤已完成订单
|
||||
|
||||
---
|
||||
|
||||
## [1.1.0] - 2026-06-16
|
||||
|
||||
### 重构
|
||||
- 登录页与菜单页分离:新增 `00-login.html` 独立登录页,`00-welcome.html` 改为纯功能菜单页
|
||||
- 任务列表页重构为三层结构:订单号(第一层)→ 任务号(第二层)→ 净菜项(第三层)
|
||||
- 新增 Tab 切换:「净菜包打包」/「餐品组合打包」两种模式
|
||||
- 称重打包页支持两种模式:净菜包模式(AI识别称重)和餐品组合模式(自动匹配子项)
|
||||
- 所有页面统一 PAD 居中外壳(`.device-frame` 1280×720)
|
||||
|
||||
### 删除
|
||||
- `03-history.html` — 打包记录页(冗余功能移除)
|
||||
- `04-settings.html` — 设备设置页(冗余功能移除)
|
||||
|
||||
### 调整
|
||||
- 导航页 `index.html` 同步更新页面列表和描述
|
||||
- 任务列表按期望到货时间升序排列
|
||||
|
||||
---
|
||||
|
||||
## [1.0.0] - 2026-06-13
|
||||
|
||||
### 新增
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
# 净菜配比秤 — 产品需求文档
|
||||
|
||||
> 原型目录:`other-module/canteen-device/ratio-scale/`
|
||||
> 创建时间:2026-06-13 | 最后更新:2026-06-16
|
||||
|
||||
---
|
||||
|
||||
## 一、模块概述
|
||||
|
||||
净菜配比秤是食堂净菜打包流程中的核心硬件终端,承担打包任务管理、净菜识别称重、餐品组合打包三大职能。设备配备触摸屏、称重传感器、食材识别摄像头和人脸识别摄像头,支持「净菜包打包」和「餐品组合打包」两种业务模式。
|
||||
|
||||
### 业务流程
|
||||
|
||||
```
|
||||
用户登录 → 查看打包任务(按期望到货时间排序)→ 净材识别录入 → 完成任务
|
||||
```
|
||||
|
||||
**任务结构(三层)**:
|
||||
- 第一层:打包任务(关联后台系统外采内供订单号)
|
||||
- 第二层:净菜/餐品(净菜包 或 餐品净菜包)
|
||||
- 第三层:餐品净菜包的净菜明细(仅餐品净菜包类型)
|
||||
|
||||
**打包流程**:
|
||||
1. 先按照任务把所有净菜包打包完成
|
||||
2. 随后查询任务单里的餐品净菜包,系统自动匹配已打包净菜进行组合打包
|
||||
|
||||
### 页面导航结构
|
||||
|
||||
```
|
||||
00 登录页(人脸识别 / 账号密码登录)
|
||||
└── 登录成功后进入
|
||||
00 功能菜单页
|
||||
├── 今日任务 → 01-packing-tasks
|
||||
│ ├── Tab: 净菜包打包
|
||||
│ └── Tab: 餐品组合打包
|
||||
└── 称重打包 → 02-weighing-packing
|
||||
├── 模式 A: 净菜包打包(AI 识别 + 称重 + 塑封)
|
||||
── 模式 B: 餐品组合打包(自动匹配子项)
|
||||
```
|
||||
|
||||
#### 页面间跳转关系
|
||||
|
||||
| 来源页 | 触发操作 | 目标页 | 携带参数 |
|
||||
|--------|----------|--------|----------|
|
||||
| 根导航(index.html) | 进入净菜配比秤 | 00 登录页 | — |
|
||||
| 00 登录页 | 登录成功 | 00 功能菜单页 | `?user=姓名&uid=工号` |
|
||||
| 00 功能菜单页 | 点击「今日任务」 | 01 任务列表页 | `?user=...&uid=...` |
|
||||
| 00 功能菜单页 | 点击「称重打包」 | 02 称重打包页 | `?user=...&uid=...` |
|
||||
| 00 功能菜单页 | 点击「退出登录」 | 00 登录页 | — |
|
||||
| 01 任务列表页 | 点击「去打包」 | 02 称重打包页 | `?task=任务号&item=序号&type=veg/meal&user=...` |
|
||||
| 01 任务列表页 | 顶栏 ← 返回 | 00 功能菜单页 | — |
|
||||
| 02 称重打包页 | 顶栏 ← 返回 | 01 任务列表页 | — |
|
||||
|
||||
### 核心状态流转
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[登录页] -->|人脸识别/账号登录| B[功能菜单页]
|
||||
B -->|今日任务| C[任务列表页]
|
||||
B -->|称重打包| D[称重打包页]
|
||||
B -->|退出登录| A
|
||||
|
||||
C -->|Tab: 净菜包打包| C1[净菜包任务列表]
|
||||
C -->|Tab: 餐品组合打包| C2[餐品组合任务列表]
|
||||
|
||||
C1 -->|点击去打包| D1[净菜包模式]
|
||||
C2 -->|点击去打包| D2[餐品组合模式]
|
||||
|
||||
D1 --> E[放置食材]
|
||||
E --> F[AI 识别品类]
|
||||
F --> G[称重稳定]
|
||||
G --> H[打包 + 塑封]
|
||||
H -->|继续打包| E
|
||||
H -->|返回| C
|
||||
|
||||
D2 --> I[放置食材]
|
||||
I --> J[AI 识别净菜]
|
||||
J --> K{匹配子项?}
|
||||
K -->|匹配成功| L[标记子项完成]
|
||||
K -->|未匹配| M[提示不匹配]
|
||||
L --> N{所有子项完成?}
|
||||
N -->|是| O[组合打包]
|
||||
N -->|否| I
|
||||
O -->|返回| C
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、页面清单
|
||||
|
||||
| 编号 | 文件名 | 页面名称 | 类型 | 原型链接 |
|
||||
|------|--------|----------|------|----------|
|
||||
| 00 | `00-login.html` | 登录页 | 功能页 | [打开原型](../00-login.html) |
|
||||
| 00 | `00-welcome.html` | 功能菜单页 | 功能页 | [打开原型](../00-welcome.html) |
|
||||
| 01 | `01-packing-tasks.html` | 今日打包任务 | 功能页 | [打开原型](../01-packing-tasks.html) |
|
||||
| 02 | `02-weighing-packing.html` | 称重打包 | 功能页 | [打开原型](../02-weighing-packing.html) |
|
||||
|
||||
---
|
||||
|
||||
## 三、页面详细说明
|
||||
|
||||
### 3.1 登录页 `00-login.html`
|
||||
|
||||
**页面定位**:员工身份验证入口
|
||||
|
||||
**功能说明**:
|
||||
- 支持人脸识别和账号密码两种登录方式
|
||||
- 登录成功后自动跳转到功能菜单页
|
||||
- 显示登录员工姓名、部门、工号信息
|
||||
|
||||
**交互说明**:
|
||||
- 点击人脸识别区 → 启动识别动画 → 2 秒后模拟识别成功
|
||||
- 切换登录方式 Tab → 切换显示人脸/密码表单
|
||||
- 账号密码登录 → 验证工号和密码 → 成功则跳转
|
||||
|
||||
**演示账号**:
|
||||
| 工号 | 密码 | 姓名 | 角色 |
|
||||
|------|------|------|------|
|
||||
| 30001 | 123456 | 刘九 | 打包员 |
|
||||
| 30002 | 123456 | 陈十 | 打包员 |
|
||||
| 30003 | 123456 | 杨一 | 质检员 |
|
||||
|
||||
---
|
||||
|
||||
### 3.2 功能菜单页 `00-welcome.html`
|
||||
|
||||
**页面定位**:登录后功能导航入口
|
||||
|
||||
**功能说明**:
|
||||
- 显示当前登录用户信息
|
||||
- 提供「今日任务」和「称重打包」两个功能入口
|
||||
- 支持退出登录返回登录页
|
||||
- 新任务到达时显示脉冲动画和角标提示
|
||||
|
||||
**交互说明**:
|
||||
- 页面加载时检查登录状态,未登录自动跳转登录页
|
||||
- 每 30 秒轮询检测新任务到达
|
||||
- 点击功能按钮携带用户参数跳转到对应页面
|
||||
|
||||
---
|
||||
|
||||
### 3.3 今日打包任务 `01-packing-tasks.html`
|
||||
|
||||
**页面定位**:打包任务列表管理
|
||||
|
||||
**功能说明**:
|
||||
- Tab 切换:「净菜包打包」/「餐品组合打包」
|
||||
- 三层结构展示:订单号 → 任务号 → 净菜项
|
||||
- 按期望到货时间升序排列(最紧急的在最上面)
|
||||
- 显示每种净菜的打包进度和状态
|
||||
|
||||
**数据结构**:
|
||||
```
|
||||
订单 #PO-20260616-001(期望到货 11:30)
|
||||
└── 任务 #T-001
|
||||
├── 🥔 土豆丝(净菜包)需 2.5 斤 已包 1.0 斤 [进行中]
|
||||
├── 🥕 胡萝卜丝(净菜包)需 1.8 斤 已包 1.8 斤 [已完成]
|
||||
└── 📦 宫保鸡丁套餐(餐品净菜包)需 3 份 已包 0 份
|
||||
├── 土豆丝 1.5 斤
|
||||
├── 胡萝卜丝 0.8 斤
|
||||
└── 黄瓜片 0.5 斤
|
||||
```
|
||||
|
||||
**交互说明**:
|
||||
- 点击净菜包「去打包」→ 跳转称重打包页(净菜包模式)
|
||||
- 点击餐品净菜包「去打包」→ 跳转称重打包页(餐品组合模式)
|
||||
- 已完成项显示「完成」按钮,不可再次操作
|
||||
|
||||
---
|
||||
|
||||
### 3.4 称重打包 `02-weighing-packing.html`
|
||||
|
||||
**页面定位**:净菜识别、称重、打包操作
|
||||
|
||||
**功能说明**:
|
||||
|
||||
**净菜包模式**:
|
||||
- AI 识别放置的食材品类
|
||||
- 实时称重显示
|
||||
- 重量稳定后点击「打包 + 塑封」
|
||||
- 记录本次打包历史
|
||||
|
||||
**餐品组合模式**:
|
||||
- 显示餐品净菜包所需的子项清单
|
||||
- 秤上放置食材时系统自动识别并匹配对应子项
|
||||
- 匹配成功的子项显示绿色勾选
|
||||
- 所有子项匹配完成后可点击「组合打包」
|
||||
|
||||
**交互说明**:
|
||||
- 从任务列表进入时带入任务参数(任务号、净菜序号、类型)
|
||||
- 称重过程动画:数字递增 → 稳定 → 可操作
|
||||
- AI 识别结果与任务比对:匹配显示绿色,不匹配显示红色警告
|
||||
- 打包成功后记录自动添加到右侧打包记录列表
|
||||
|
||||
---
|
||||
|
||||
## 四、设计规范
|
||||
|
||||
### 4.1 视觉尺寸
|
||||
|
||||
- 设备分辨率:1280 × 720(PAD 横屏)
|
||||
- 顶部导航栏高度:44px
|
||||
- 内容区高度:calc(100% - 44px)
|
||||
|
||||
### 4.2 设计令牌
|
||||
|
||||
| 用途 | 颜色值 |
|
||||
|------|--------|
|
||||
| 背景色 | `#0e1326` |
|
||||
| 卡片背景 | `#1a2b4a` |
|
||||
| 主色(按钮/高亮) | `#4a90d9` |
|
||||
| 成功色 | `#52c41a` |
|
||||
| 警告色 | `#faad16` |
|
||||
| 错误色 | `#ff4d4f` |
|
||||
| 餐品净菜包色 | `#722ed1` |
|
||||
|
||||
### 4.3 PAD 外壳规范
|
||||
|
||||
所有页面统一采用 `.device-frame` 容器:
|
||||
- 圆角:24px
|
||||
- 阴影:`0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)`
|
||||
- 内部禁止可见滚动条(`scrollbar-width: none` + `::-webkit-scrollbar { display: none }`)
|
||||
|
||||
---
|
||||
|
||||
## 五、待办事项
|
||||
|
||||
- [ ] 对接真实硬件称重传感器 API
|
||||
- [ ] 对接真实 AI 食材识别 API
|
||||
- [ ] 对接后台系统任务同步接口
|
||||
- [ ] 打包记录本地存储与同步
|
||||
- [ ] 打印标签功能(如有硬件支持)
|
||||
@@ -6,7 +6,23 @@
|
||||
<title>净菜配比秤 - 蚁熊智能餐养平台</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif; background: #0e1326; color: #fff; width: 1280px; height: 720px; overflow: hidden; }
|
||||
body {
|
||||
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
|
||||
background: #05080f; color: #fff;
|
||||
min-height: 100vh; min-width: 1280px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
/* PAD 设备外壳 */
|
||||
.device-frame {
|
||||
width: 1280px; height: 720px;
|
||||
background: #0e1326;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: flex; flex-direction: column;
|
||||
}
|
||||
.top-bar { display: flex; align-items: center; height: 44px; background: #1a2b4a; padding: 0 20px; }
|
||||
.top-bar__title { flex: 1; text-align: center; font-size: 15px; font-weight: 600; color: rgba(255,255,255,0.85); }
|
||||
.back-link { font-size: 14px; cursor: pointer; color: rgba(255,255,255,0.7); text-decoration: none; }
|
||||
@@ -22,51 +38,37 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-bar">
|
||||
<a class="back-link" href="../index.html">◀ 返回</a>
|
||||
<span class="top-bar__title">净菜配比秤</span>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a class="card" href="00-welcome.html">
|
||||
<span class="card__icon">👋</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">欢迎页面</div>
|
||||
<div class="card__desc">人脸识别/账号密码登录、功能菜单入口</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="01-packing-tasks.html">
|
||||
<span class="card__icon">📋</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">今日打包任务</div>
|
||||
<div class="card__desc">系统分配的净菜打包任务列表</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="02-weighing-packing.html">
|
||||
<span class="card__icon">📦</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">称重打包</div>
|
||||
<div class="card__desc">净菜AI识别、称重、按员工拆单打包塑封</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="03-history.html">
|
||||
<span class="card__icon">📝</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">打包记录</div>
|
||||
<div class="card__desc">历史打包记录查看与筛选</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="04-settings.html">
|
||||
<span class="card__icon">⚙️</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">设备设置</div>
|
||||
<div class="card__desc">打包参数、AI识别、秤参数配置</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<div class="device-frame">
|
||||
<div class="top-bar">
|
||||
<a class="back-link" href="../index.html">◀ 返回</a>
|
||||
<span class="top-bar__title">净菜配比秤</span>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<a class="card" href="00-login.html">
|
||||
<span class="card__icon">🔑</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">员工登录</div>
|
||||
<div class="card__desc">人脸识别/账号密码登录入口</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="00-welcome.html">
|
||||
<span class="card__icon">📋</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">功能菜单</div>
|
||||
<div class="card__desc">称重任务入口</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
<a class="card" href="01-packing-tasks.html">
|
||||
<span class="card__icon">📦</span>
|
||||
<div class="card__info">
|
||||
<div class="card__title">称重任务</div>
|
||||
<div class="card__desc">三层任务结构:订单→任务→净菜项,点击去称重直接进入称重页</div>
|
||||
</div>
|
||||
<span class="card__arrow">›</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user