diff --git a/CLAUDE.md b/CLAUDE.md index 10343be..0a98661 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ - + # 项目约束 本项目所有工作必须严格遵守 `项目背景.md` 中定义的全部规范,包括: diff --git a/index.html b/index.html index c495d93..64fd6e0 100644 --- a/index.html +++ b/index.html @@ -312,6 +312,7 @@ const SITE_MAP = [ { file:'din-canteen.html', label:'食堂管理' }, { file:'din-canteen-add.html', label:'新增食堂' }, { file:'din-canteen-line.html', label:'餐线管理' }, + { file:'din-canteen-shift.html', label:'场所排版设置' }, { file:'din-dict-mgmt.html', label:'字典管理' }, { file:'din-dict-config.html', label:'字典配置' }, { file:'din-algo-population.html', label:'群体算法' }, @@ -872,6 +873,17 @@ const SITE_MAP = [ {label:'扫码溯源', file:'trace-query.html'}, {label:'溯源链路', file:'trace-detail.html'} ] }, + { name:'营养管理餐品配送', dir:'other-module/meal-delivery-h5', entry:'01-home.html', pages:[ + {label:'配送员登录', file:'00-login.html'}, + {label:'工作台首页(模块入口)', file:'01-home.html'}, + {label:'派单接听 · 核心', file:'02-dispatch-incoming.html'}, + {label:'抢单大厅', file:'03-grab-pool.html'}, + {label:'订单详情', file:'04-order-detail.html'}, + {label:'配送中', file:'05-delivering.html'}, + {label:'送达签收', file:'06-finish-sign.html'}, + {label:'历史订单', file:'07-history.html'}, + {label:'个人中心', file:'08-profile.html'} + ] }, { name:'西安应急中心大屏', dir:'other-module/emergency-screen/xian-center', entry:'index-v4.html', pages:[ {label:'应急中心大屏', file:'index-v4.html'} ] }, diff --git a/other-module/canteen-device/checkout-device/02-standby.html b/other-module/canteen-device/checkout-device/02-standby.html index 2b274a1..c4a9c96 100644 --- a/other-module/canteen-device/checkout-device/02-standby.html +++ b/other-module/canteen-device/checkout-device/02-standby.html @@ -37,6 +37,7 @@ background: #1a2b4a; padding: 0 20px; flex-shrink: 0; + gap: 12px; } .back-btn { font-size: 13px; @@ -57,6 +58,36 @@ font-size: 12px; color: rgba(255, 255, 255, 0.5); font-family: Menlo, Consolas, monospace; + flex-shrink: 0; + } + .top-bar__right { + display: flex; + align-items: center; + gap: 10px; + flex-shrink: 0; + } + /* 顶部栏内的收银员信息(紧凑版) */ + .cashier-info--compact { + display: flex; + align-items: center; + gap: 6px; + padding: 4px 10px 4px 4px; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 16px; + } + .cashier-info--compact .cashier-info__avatar { + width: 22px; + height: 22px; + font-size: 10px; + } + .cashier-info--compact .cashier-info__text { + font-size: 11px; + color: rgba(255, 255, 255, 0.8); + } + .logout-btn--compact { + padding: 4px 10px; + font-size: 11px; } /* 主内容 */ @@ -132,6 +163,84 @@ color: #ff6b6b; } + /* 餐次控制区 */ + .meal-ctrl { + display: flex; + flex-direction: column; + gap: 10px; + padding: 14px 18px; + background: rgba(26, 43, 74, 0.4); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 14px; + min-width: 200px; + } + .meal-ctrl__status { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + font-weight: 600; + } + .meal-ctrl__status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; + } + .meal-ctrl__status-dot--live { + background: #4ade80; + box-shadow: 0 0 8px rgba(74, 222, 128, 0.5); + animation: dotBlink2 1.4s infinite; + } + .meal-ctrl__status-dot--off { + background: #94a3b8; + } + @keyframes dotBlink2 { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.35; } + } + .meal-ctrl__status-text { color: #fff; } + .meal-ctrl__status-text--live { color: #4ade80; } + .meal-ctrl__status-text--off { color: rgba(255, 255, 255, 0.5); } + .meal-ctrl__buttons { + display: flex; + gap: 8px; + } + .meal-ctrl__btn { + flex: 1; + height: 38px; + border-radius: 10px; + font-size: 13px; + font-weight: 600; + cursor: pointer; + border: 1px solid; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 5px; + transition: all 0.2s; + text-decoration: none; + } + .meal-ctrl__btn--start { + background: linear-gradient(135deg, rgba(74, 222, 128, 0.18), rgba(34, 197, 94, 0.12)); + border-color: rgba(74, 222, 128, 0.4); + color: #4ade80; + } + .meal-ctrl__btn--start:hover { + background: linear-gradient(135deg, rgba(74, 222, 128, 0.28), rgba(34, 197, 94, 0.2)); + border-color: rgba(74, 222, 128, 0.6); + box-shadow: 0 4px 14px rgba(74, 222, 128, 0.2); + } + .meal-ctrl__btn--stop { + background: rgba(239, 68, 68, 0.1); + border-color: rgba(239, 68, 68, 0.3); + color: #f87171; + } + .meal-ctrl__btn--stop:hover { + background: rgba(239, 68, 68, 0.2); + border-color: rgba(239, 68, 68, 0.5); + } + /* 中央:核心动作区 */ .hero { flex: 1; @@ -466,6 +575,254 @@ font-size: 11px; color: rgba(255, 255, 255, 0.5); } + + /* ============ 交接班弹窗 ============ */ + .shift-overlay { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.72); + backdrop-filter: blur(6px); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; + border-radius: 24px; + } + .shift-modal { + width: 680px; + max-height: 680px; + background: linear-gradient(180deg, #1a2744 0%, #141e36 100%); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 18px; + padding: 28px 32px 24px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 120px rgba(74, 144, 217, 0.08); + overflow: hidden; + } + .shift-modal__head { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + } + .shift-modal__title { + font-size: 18px; + font-weight: 700; + color: #fff; + } + .shift-modal__close { + width: 30px; + height: 30px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.1); + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + color: rgba(255, 255, 255, 0.55); + cursor: pointer; + transition: all 0.2s; + } + .shift-modal__close:hover { + background: rgba(245, 34, 45, 0.2); + border-color: rgba(245, 34, 45, 0.4); + color: #ff6b6b; + } + + /* 收银员信息条 */ + .shift-modal__cashier { + display: flex; + align-items: center; + gap: 12px; + padding: 14px 16px; + background: rgba(0, 0, 0, 0.25); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 12px; + margin-bottom: 20px; + } + .shift-modal__cashier-avatar { + width: 40px; + height: 40px; + border-radius: 50%; + background: linear-gradient(135deg, #4a90d9, #0AC4A8); + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + font-weight: 700; + flex-shrink: 0; + } + .shift-modal__cashier-info { + display: flex; + flex-direction: column; + gap: 4px; + } + .shift-modal__cashier-name { + font-size: 14px; + font-weight: 600; + color: #fff; + } + .shift-modal__cashier-meta { + font-size: 12px; + color: rgba(255, 255, 255, 0.5); + } + + /* 统计指标网格 */ + .shift-modal__kpi-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + } + .shift-kpi { + background: rgba(0, 0, 0, 0.2); + border: 1px solid rgba(255, 255, 255, 0.05); + border-radius: 10px; + padding: 14px 16px; + display: flex; + flex-direction: column; + gap: 6px; + } + .shift-kpi__label { + font-size: 11px; + color: rgba(255, 255, 255, 0.5); + } + .shift-kpi__value { + font-size: 20px; + font-weight: 700; + color: #fff; + display: flex; + align-items: baseline; + gap: 4px; + } + .shift-kpi__value--green { color: #4ade80; } + .shift-kpi__value--gold { color: #fbbf24; } + .shift-kpi__unit { + font-size: 12px; + font-weight: 400; + color: rgba(255, 255, 255, 0.55); + } + .shift-kpi__hint { + font-size: 10px; + color: rgba(255, 255, 255, 0.35); + line-height: 1.4; + } + .shift-modal__kpi-grid--two { + grid-template-columns: 1fr 1fr; + } + + /* 分区标题 */ + .shift-modal__section { + margin-bottom: 12px; + } + .shift-modal__section-title { + font-size: 13px; + font-weight: 600; + color: rgba(255, 255, 255, 0.7); + margin-bottom: 10px; + display: flex; + align-items: center; + gap: 6px; + } + + /* 支付方式明细表 */ + .shift-pay-table { + background: rgba(0, 0, 0, 0.2); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 10px; + overflow: hidden; + } + .shift-pay-table__head { + display: flex; + padding: 8px 16px; + background: rgba(255, 255, 255, 0.04); + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + } + .shift-pay-table__th { + font-size: 11px; + color: rgba(255, 255, 255, 0.45); + font-weight: 500; + } + .shift-pay-table__th--name { flex: 1; } + .shift-pay-table__th--num { width: 80px; text-align: right; } + .shift-pay-table__row { + display: flex; + padding: 9px 16px; + align-items: center; + border-bottom: 1px solid rgba(255, 255, 255, 0.04); + transition: background 0.15s; + } + .shift-pay-table__row:last-child { border-bottom: none; } + .shift-pay-table__row:hover { background: rgba(255, 255, 255, 0.03); } + .shift-pay-table__row--total { + background: rgba(255, 255, 255, 0.04); + font-weight: 700; + border-top: 1px solid rgba(255, 255, 255, 0.08); + } + .shift-pay-table__td { + font-size: 13px; + color: rgba(255, 255, 255, 0.85); + } + .shift-pay-table__td--name { flex: 1; display: flex; align-items: center; gap: 8px; } + .shift-pay-table__td--num { width: 80px; text-align: right; font-variant-numeric: tabular-nums; font-family: Menlo, Consolas, monospace; font-size: 12px; } + .shift-pay-table__row--total .shift-pay-table__td { color: #fff; } + + /* 支付方式色点 */ + .shift-pay-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; + } + .shift-pay-dot--online { background: #4ade80; box-shadow: 0 0 6px rgba(74, 222, 128, 0.5); } + .shift-pay-dot--cash { background: #fb923c; box-shadow: 0 0 6px rgba(251, 146, 60, 0.5); } + .shift-pay-dot--balance { background: #60a5fa; box-shadow: 0 0 6px rgba(96, 165, 250, 0.5); } + + /* 分割线 */ + .shift-modal__divider { + height: 1px; + background: rgba(255, 255, 255, 0.08); + margin: 20px 0; + } + + /* 底部操作区 */ + .shift-modal__actions { + display: flex; + gap: 12px; + justify-content: flex-end; + } + .shift-modal__btn { + height: 40px; + border-radius: 10px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + border: 1px solid; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 28px; + text-decoration: none; + transition: all 0.2s; + } + .shift-modal__btn--cancel { + background: rgba(255, 255, 255, 0.06); + border-color: rgba(255, 255, 255, 0.12); + color: rgba(255, 255, 255, 0.7); + } + .shift-modal__btn--cancel:hover { + background: rgba(255, 255, 255, 0.1); + color: #fff; + } + .shift-modal__btn--exit { + background: linear-gradient(135deg, rgba(245, 34, 45, 0.18), rgba(239, 68, 68, 0.12)); + border-color: rgba(245, 34, 45, 0.4); + color: #ff6b6b; + } + .shift-modal__btn--exit:hover { + background: linear-gradient(135deg, rgba(245, 34, 45, 0.3), rgba(239, 68, 68, 0.22)); + border-color: rgba(245, 34, 45, 0.6); + box-shadow: 0 4px 16px rgba(245, 34, 45, 0.2); + } @@ -477,6 +834,13 @@ ◀ 返回主页 结算台待机 2026-08-06 周四 +
+
+
+
CS001 · 张三
+
+ 交接班 +
@@ -491,11 +855,21 @@
数味餐厅 · 一楼 A 区 2 号餐线 · 等待顾客取餐
-
-
-
CS001 · 张三
+ +
+
+ + 午餐开餐中 +
+
+ + + 🥢 收餐 + +
- 退出登录
@@ -585,7 +959,7 @@
今日数据可视化
- +
🍽️
餐次管理
@@ -607,6 +981,7 @@ + +
+ diff --git a/other-module/canteen-device/checkout-device/07-statistics.html b/other-module/canteen-device/checkout-device/07-statistics.html index 7111be6..a1d3a89 100644 --- a/other-module/canteen-device/checkout-device/07-statistics.html +++ b/other-module/canteen-device/checkout-device/07-statistics.html @@ -131,18 +131,6 @@ border-color: #4a90d9; color: #fff; } - .meal-select { - padding: 6px 12px; - background: rgba(82, 196, 26, 0.12); - border: 1px solid rgba(82, 196, 26, 0.35); - border-radius: 6px; - color: #4ade80; - font-size: 12px; - cursor: pointer; - font-weight: 600; - font-family: inherit; - } - .meal-select option { background: #1a2b4a; color: #fff; } /* 自定义日期输入 */ .date-input { padding: 6px 10px; @@ -680,6 +668,527 @@ color: #fff; font-weight: 600; } + + /* ===== Tab 3: 餐次历史(mh- 前缀,避免与统计页样式冲突) ===== */ + .tab-panel--meal-history { + display: none; + grid-template-columns: 280px 1fr; + gap: 14px; + } + .tab-panel--meal-history.active { + display: grid; + } + + /* 左侧:餐次列表 */ + .mh-meal-list { + display: flex; + flex-direction: column; + background: rgba(26, 43, 74, 0.4); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 12px; + overflow: hidden; + } + .mh-meal-list__header { + padding: 12px 14px; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + display: flex; + justify-content: space-between; + align-items: center; + } + .mh-meal-list__title { + font-size: 13px; + font-weight: 600; + color: #fff; + display: flex; + align-items: center; + gap: 6px; + } + .mh-meal-list__title::before { + content: ""; + width: 3px; + height: 12px; + background: #4a90d9; + border-radius: 2px; + } + .mh-meal-list__count { + font-size: 10px; + color: rgba(255, 255, 255, 0.55); + padding: 2px 6px; + background: rgba(255, 255, 255, 0.08); + border-radius: 8px; + } + .mh-meal-list__body { + flex: 1; + overflow-y: auto; + scrollbar-width: none; + padding: 8px 0; + } + .mh-meal-list__body::-webkit-scrollbar { display: none; } + + .mh-date-group { margin-bottom: 8px; } + .mh-date-group__title { + font-size: 11px; + color: rgba(255, 255, 255, 0.45); + padding: 8px 14px 4px; + letter-spacing: 0.5px; + } + + .mh-meal-item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 14px; + cursor: pointer; + transition: all 0.2s; + border-left: 3px solid transparent; + } + .mh-meal-item:hover { background: rgba(74, 144, 217, 0.08); } + .mh-meal-item.is-active { + background: rgba(74, 144, 217, 0.15); + border-left-color: #4a90d9; + } + .mh-meal-item__emoji { + width: 28px; + height: 28px; + border-radius: 8px; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + background: rgba(255, 255, 255, 0.06); + flex-shrink: 0; + } + .mh-meal-item__body { flex: 1; min-width: 0; } + .mh-meal-item__name { + font-size: 12px; + color: #fff; + font-weight: 600; + margin-bottom: 2px; + } + .mh-meal-item__meta { font-size: 10px; color: rgba(255, 255, 255, 0.5); } + .mh-meal-item__status { + font-size: 10px; + padding: 2px 6px; + border-radius: 6px; + font-weight: 600; + flex-shrink: 0; + } + .mh-meal-item__status--done { background: rgba(148, 163, 184, 0.15); color: #cbd5e1; } + .mh-meal-item__status--live { background: rgba(74, 222, 128, 0.18); color: #4ade80; } + .mh-meal-item__status--pending { background: rgba(255, 255, 255, 0.06); color: rgba(255, 255, 255, 0.4); } + + /* 右侧:流程详情面板 */ + .mh-detail-panel { + display: flex; + flex-direction: column; + background: rgba(26, 43, 74, 0.4); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 12px; + overflow: hidden; + } + .mh-detail-header { + padding: 14px 18px; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + display: flex; + align-items: center; + gap: 14px; + flex-wrap: wrap; + flex-shrink: 0; + } + .mh-detail-header__title { + font-size: 16px; + font-weight: 700; + color: #fff; + display: flex; + align-items: center; + gap: 8px; + } + .mh-detail-header__pill { + display: inline-flex; + align-items: center; + gap: 5px; + padding: 4px 10px; + border-radius: 10px; + font-size: 11px; + font-weight: 600; + } + .mh-detail-header__pill--done { background: rgba(148, 163, 184, 0.18); color: #cbd5e1; } + .mh-detail-header__pill--live { + background: rgba(74, 222, 128, 0.18); + color: #4ade80; + } + .mh-detail-header__pill--live::before { + content: ""; + width: 5px; + height: 5px; + border-radius: 50%; + background: #4ade80; + animation: mhDotBlink 1.4s infinite; + } + @keyframes mhDotBlink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.35; } + } + .mh-detail-header__spacer { flex: 1; } + .mh-detail-header__info { + display: flex; + align-items: center; + gap: 16px; + font-size: 11px; + color: rgba(255, 255, 255, 0.65); + } + .mh-detail-header__info-item { + display: flex; + align-items: center; + gap: 4px; + } + .mh-detail-header__info-item strong { color: #fff; font-weight: 600; } + + /* 明细视图副头部 */ + .mh-detail-subhead { + display: none; + align-items: center; + gap: 12px; + padding: 10px 18px; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + flex-shrink: 0; + background: rgba(0, 0, 0, 0.15); + } + .mh-detail-subhead--show { display: flex; } + .mh-detail-subhead__back { + font-size: 12px; + color: rgba(255, 255, 255, 0.6); + cursor: pointer; + transition: color 0.2s; + white-space: nowrap; + } + .mh-detail-subhead__back:hover { color: #fff; } + .mh-detail-subhead__badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 3px 10px; + border-radius: 8px; + font-size: 11px; + font-weight: 700; + } + .mh-detail-subhead__badge--start { background: rgba(74, 222, 128, 0.18); color: #4ade80; } + .mh-detail-subhead__badge--add { background: rgba(251, 191, 36, 0.18); color: #fbbf24; } + .mh-detail-subhead__badge--close { background: rgba(148, 163, 184, 0.18); color: #cbd5e1; } + .mh-detail-subhead__badge--dispose { background: rgba(168, 85, 247, 0.18); color: #c084fc; } + .mh-detail-subhead__title { font-size: 13px; font-weight: 600; color: #fff; } + .mh-detail-subhead__time { + margin-left: auto; + font-size: 11px; + color: rgba(255, 255, 255, 0.5); + font-family: Menlo, Consolas, monospace; + } + + /* 时间轴容器 */ + .mh-timeline-wrap { + flex: 1; + overflow-y: auto; + scrollbar-width: none; + padding: 16px 24px 24px; + } + .mh-timeline-wrap::-webkit-scrollbar { display: none; } + + .mh-timeline { + position: relative; + padding-left: 28px; + } + .mh-timeline::before { + content: ""; + position: absolute; + left: 11px; + top: 8px; + bottom: 8px; + width: 2px; + background: linear-gradient(180deg, + rgba(74, 222, 128, 0.4) 0%, + rgba(251, 191, 36, 0.3) 40%, + rgba(148, 163, 184, 0.3) 70%, + rgba(168, 85, 247, 0.3) 100% + ); + } + + .mh-tl-node { + position: relative; + padding: 8px 0 18px 18px; + } + .mh-tl-node:last-child { padding-bottom: 0; } + + .mh-tl-node__dot { + position: absolute; + left: -28px; + top: 10px; + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + border: 2px solid #0e1326; + z-index: 2; + } + .mh-tl-node__dot--start { background: #4ade80; box-shadow: 0 0 12px rgba(74, 222, 128, 0.4); } + .mh-tl-node__dot--add { background: #fbbf24; box-shadow: 0 0 12px rgba(251, 191, 36, 0.4); } + .mh-tl-node__dot--close { background: #94a3b8; box-shadow: 0 0 8px rgba(148, 163, 184, 0.3); } + .mh-tl-node__dot--dispose { background: #a855f7; box-shadow: 0 0 12px rgba(168, 85, 247, 0.4); } + + .mh-tl-node__card { + padding: 12px 16px; + background: rgba(0, 0, 0, 0.25); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 10px; + transition: all 0.2s; + cursor: pointer; + position: relative; + } + .mh-tl-node__card:hover { + background: rgba(0, 0, 0, 0.35); + border-color: rgba(255, 255, 255, 0.15); + } + .mh-tl-node__card.is-focused { + border-color: rgba(74, 144, 217, 0.5); + box-shadow: 0 0 12px rgba(74, 144, 217, 0.2); + } + + .mh-tl-node__head { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 6px; + gap: 10px; + } + .mh-tl-node__title { + font-size: 13px; + font-weight: 700; + color: #fff; + display: flex; + align-items: center; + gap: 6px; + } + .mh-tl-node__time { + font-size: 11px; + color: rgba(255, 255, 255, 0.55); + font-family: Menlo, Consolas, monospace; + } + .mh-tl-node__desc { + font-size: 11px; + color: rgba(255, 255, 255, 0.65); + line-height: 1.5; + margin-bottom: 6px; + } + .mh-tl-node__desc strong { color: #fff; font-weight: 600; } + .mh-tl-node__tags { + display: flex; + gap: 6px; + flex-wrap: wrap; + align-items: center; + } + .mh-tl-node__open { + margin-left: auto; + font-size: 10px; + color: rgba(74, 144, 217, 0.7); + white-space: nowrap; + flex-shrink: 0; + } + .mh-tl-node__card:hover .mh-tl-node__open { color: #60a5fa; } + + .mh-tl-tag { + display: inline-flex; + align-items: center; + gap: 3px; + padding: 2px 8px; + border-radius: 6px; + font-size: 10px; + font-weight: 600; + } + .mh-tl-tag--green { background: rgba(74, 222, 128, 0.18); color: #4ade80; } + .mh-tl-tag--blue { background: rgba(74, 144, 217, 0.18); color: #60a5fa; } + .mh-tl-tag--gold { background: rgba(251, 191, 36, 0.18); color: #fbbf24; } + .mh-tl-tag--gray { background: rgba(148, 163, 184, 0.15); color: #cbd5e1; } + .mh-tl-tag--red { background: rgba(239, 68, 68, 0.18); color: #ef4444; } + .mh-tl-tag--purple { background: rgba(168, 85, 247, 0.18); color: #c084fc; } + + /* 明细汇总条 */ + .mh-detail-summary { + display: flex; + gap: 10px; + flex-wrap: wrap; + margin-bottom: 14px; + } + .mh-ds-card { + flex: 1; + min-width: 140px; + padding: 10px 14px; + background: rgba(0, 0, 0, 0.2); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 8px; + display: flex; + flex-direction: column; + gap: 3px; + } + .mh-ds-card__label { font-size: 10px; color: rgba(255, 255, 255, 0.5); } + .mh-ds-card__value { + font-size: 15px; + font-weight: 700; + color: #fff; + } + .mh-ds-card__value--green { color: #4ade80; } + .mh-ds-card__value--gold { color: #fbbf24; } + .mh-ds-card__value--blue { color: #60a5fa; } + + /* 明细表格 */ + .mh-detail-table-wrap { + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 8px; + } + .mh-detail-table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + font-size: 11px; + } + .mh-detail-table thead th { + position: sticky; + top: 0; + background: #1a2b4a; + color: rgba(255, 255, 255, 0.55); + font-weight: 600; + font-size: 10px; + text-align: left; + padding: 9px 10px; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + white-space: nowrap; + } + .mh-detail-table tbody td { + padding: 9px 10px; + color: rgba(255, 255, 255, 0.8); + border-bottom: 1px solid rgba(255, 255, 255, 0.04); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + .mh-detail-table tbody tr:hover td { background: rgba(74, 144, 217, 0.06); } + .mh-detail-table tbody tr:last-child td { border-bottom: none; } + .mh-detail-table__total td { + border-top: 1px solid rgba(251, 191, 36, 0.3) !important; + color: #fbbf24 !important; + font-weight: 700; + background: rgba(251, 191, 36, 0.05) !important; + } + .mh-detail-table .mh-col-num { + text-align: right; + font-family: Menlo, Consolas, monospace; + } + + /* 处置方式汇总卡片网格 */ + .mh-dmethod-grid { display: flex; gap: 10px; margin-bottom: 14px; } + .mh-dmethod-card { + flex: 1; + padding: 12px 14px; + border-radius: 10px; + border: 1px solid; + display: flex; + flex-direction: column; + gap: 4px; + text-align: center; + } + .mh-dmethod-card--welfare { background: rgba(74, 144, 217, 0.08); border-color: rgba(74, 144, 217, 0.2); } + .mh-dmethod-card--donate { background: rgba(74, 222, 128, 0.08); border-color: rgba(74, 222, 128, 0.2); } + .mh-dmethod-card--waste { background: rgba(239, 68, 68, 0.08); border-color: rgba(239, 68, 68, 0.2); } + .mh-dmethod-card--reprocess { background: rgba(168, 85, 247, 0.08); border-color: rgba(168, 85, 247, 0.2); } + .mh-dmethod-card__label { font-size: 10px; color: rgba(255, 255, 255, 0.55); } + .mh-dmethod-card__value { font-size: 20px; font-weight: 700; color: #fff; } + .mh-dmethod-card__count { font-size: 10px; color: rgba(255, 255, 255, 0.45); } + .mh-dmethod-card--welfare .mh-dmethod-card__value { color: #60a5fa; } + .mh-dmethod-card--donate .mh-dmethod-card__value { color: #4ade80; } + .mh-dmethod-card--waste .mh-dmethod-card__value { color: #ef4444; } + .mh-dmethod-card--reprocess .mh-dmethod-card__value { color: #c084fc; } + + /* 筛选 tab */ + .mh-filter-tabs { display: flex; gap: 8px; margin-bottom: 12px; } + .mh-filter-tab { + padding: 4px 12px; + border-radius: 14px; + font-size: 11px; + font-weight: 600; + color: rgba(255, 255, 255, 0.5); + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.06); + cursor: pointer; + transition: all 0.2s; + } + .mh-filter-tab:hover { color: rgba(255, 255, 255, 0.8); border-color: rgba(255, 255, 255, 0.15); } + .mh-filter-tab.is-active { + color: #fff; + background: rgba(74, 144, 217, 0.2); + border-color: rgba(74, 144, 217, 0.4); + } + + /* 处置方式徽标 */ + .mh-method-badge { + display: inline-block; + padding: 1px 8px; + border-radius: 4px; + font-size: 10px; + font-weight: 600; + } + .mh-method-badge--welfare { background: rgba(74, 144, 217, 0.18); color: #60a5fa; } + .mh-method-badge--donate { background: rgba(74, 222, 128, 0.18); color: #4ade80; } + .mh-method-badge--waste { background: rgba(239, 68, 68, 0.18); color: #ef4444; } + .mh-method-badge--reprocess { background: rgba(168, 85, 247, 0.18); color: #c084fc; } + + /* 节点卡片内的处置方式紧凑网格 */ + .mh-dispose-compact { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 4px 10px; + margin-top: 8px; + padding-top: 8px; + border-top: 1px dashed rgba(255, 255, 255, 0.08); + } + .mh-dispose-compact__item { display: flex; justify-content: space-between; font-size: 10px; gap: 4px; } + .mh-dispose-compact__label { color: rgba(255, 255, 255, 0.5); } + .mh-dispose-compact__value { color: #fff; font-weight: 600; } + + /* 底部统计卡 */ + .mh-detail-footer { + padding: 14px 20px; + border-top: 1px solid rgba(255, 255, 255, 0.06); + display: flex; + align-items: center; + gap: 18px; + background: linear-gradient(135deg, rgba(74, 144, 217, 0.08), rgba(26, 43, 74, 0.4)); + flex-shrink: 0; + } + .mh-footer-stat { display: flex; flex-direction: column; gap: 2px; } + .mh-footer-stat__label { font-size: 10px; color: rgba(255, 255, 255, 0.55); } + .mh-footer-stat__value { + font-size: 16px; + font-weight: 700; + color: #fff; + display: flex; + align-items: baseline; + gap: 2px; + } + .mh-footer-stat__value--green { color: #4ade80; } + .mh-footer-stat__value--gold { color: #fbbf24; } + .mh-footer-stat__value--red { color: #ef4444; } + .mh-footer-stat__unit { + font-size: 10px; + font-weight: 400; + color: rgba(255, 255, 255, 0.55); + } + .mh-footer-divider { + width: 1px; + height: 28px; + background: rgba(255, 255, 255, 0.1); + } @@ -694,30 +1203,25 @@
+
- 2026-08-06 14:25 + 2026-08-10 14:25
- +
- - - + + +
- - +
数据更新:14:25:30 @@ -993,12 +1497,50 @@
+ +
+ + +
+
+ 餐次列表 + 5 餐次 +
+
+ +
+
+ + +
+
+ +
+ +
+ ◀ 返回时间轴 + + + +
+
+
+ +
+
+ +
+ +
+
diff --git a/other-module/canteen-device/checkout-device/10-meal-center.html b/other-module/canteen-device/checkout-device/10-meal-center.html deleted file mode 100644 index efee42b..0000000 --- a/other-module/canteen-device/checkout-device/10-meal-center.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - 结算设备 - 餐次管理 | 蚁熊智能餐养平台 - - - - -
- - -
- ◀ 返回待机 - 餐次管理 - 2026-08-10 周一 -
- - -
余量处置已提交 ✓
- - -
- - -
-
🥪
-
-
当前餐次 · 午餐
-
数味餐厅 · 一楼 | 共 3 条餐线 · 28 道菜
-
-
12:30:45
-
- - - - -
- -
- - - - - diff --git a/other-module/canteen-device/checkout-device/11-meal-active.html b/other-module/canteen-device/checkout-device/11-meal-active.html index 31b776c..f34023b 100644 --- a/other-module/canteen-device/checkout-device/11-meal-active.html +++ b/other-module/canteen-device/checkout-device/11-meal-active.html @@ -459,6 +459,140 @@ opacity: 1; transform: translateX(-50%) translateY(0); } + + /* 已收餐状态:信息条变琥珀色调 */ + .meal-info-bar--collected { + background: linear-gradient(135deg, rgba(251, 191, 36, 0.12) 0%, rgba(26, 43, 74, 0.6) 100%); + border-color: rgba(251, 191, 36, 0.3); + } + .meal-info-bar--collected .meal-info-bar__icon { + background: rgba(251, 191, 36, 0.22); + } + .meal-info-bar__live--collected { + background: rgba(251, 191, 36, 0.18); + border-color: rgba(251, 191, 36, 0.4); + color: #fbbf24; + } + .meal-info-bar__live--collected::before { + background: #fbbf24; + } + + /* ===== 收餐弹窗:双卡片选项 ===== */ + .modal--wide { width: 500px; } + .collect-cards { + display: flex; + gap: 14px; + margin-bottom: 14px; + } + .collect-card { + flex: 1; + padding: 18px 16px 14px; + border-radius: 12px; + border: 1.5px solid; + display: flex; + flex-direction: column; + gap: 8px; + cursor: pointer; + transition: all 0.2s; + text-decoration: none; + } + .collect-card:hover { + transform: translateY(-2px); + } + .collect-card--employee { + background: linear-gradient(180deg, rgba(251, 191, 36, 0.12) 0%, rgba(26, 43, 74, 0.4) 100%); + border-color: rgba(251, 191, 36, 0.4); + } + .collect-card--employee:hover { + border-color: rgba(251, 191, 36, 0.65); + box-shadow: 0 6px 20px rgba(251, 191, 36, 0.15); + } + .collect-card--dispose { + background: linear-gradient(180deg, rgba(168, 85, 247, 0.12) 0%, rgba(26, 43, 74, 0.4) 100%); + border-color: rgba(168, 85, 247, 0.4); + } + .collect-card--dispose:hover { + border-color: rgba(168, 85, 247, 0.65); + box-shadow: 0 6px 20px rgba(168, 85, 247, 0.15); + } + .collect-card__step { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 50%; + font-size: 11px; + font-weight: 700; + flex-shrink: 0; + } + .collect-card--employee .collect-card__step { + background: rgba(251, 191, 36, 0.25); + color: #fbbf24; + } + .collect-card--dispose .collect-card__step { + background: rgba(168, 85, 247, 0.25); + color: #c084fc; + } + .collect-card__title { + font-size: 15px; + font-weight: 700; + color: #fff; + } + .collect-card__desc { + font-size: 11px; + color: rgba(255, 255, 255, 0.55); + line-height: 1.5; + flex: 1; + } + .collect-arrow { + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + color: rgba(255, 255, 255, 0.3); + flex-shrink: 0; + align-self: center; + } + + /* 余量处置按钮(已收餐状态下显示,琥珀渐变) */ + .footer-btn--warning { + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); + border-color: #f59e0b; + color: #fff; + box-shadow: 0 6px 18px rgba(245, 158, 11, 0.35); + } + .footer-btn--warning:hover { + background: linear-gradient(135deg, #d97706 0%, #b45309 100%); + box-shadow: 0 8px 22px rgba(245, 158, 11, 0.5); + } + + /* 已收餐提示横幅 */ + .collected-banner { + display: flex; + align-items: center; + gap: 10px; + padding: 14px 18px; + background: linear-gradient(135deg, rgba(251, 191, 36, 0.1) 0%, rgba(26, 43, 74, 0.4) 100%); + border: 1px solid rgba(251, 191, 36, 0.25); + border-radius: 12px; + margin-bottom: 14px; + } + .collected-banner__icon { + font-size: 24px; + flex-shrink: 0; + } + .collected-banner__text { + flex: 1; + font-size: 13px; + color: #fbbf24; + font-weight: 600; + } + .collected-banner__sub { + font-size: 11px; + color: rgba(255, 255, 255, 0.55); + font-weight: 400; + } @@ -467,7 +601,7 @@
- ◀ 返回餐次管理 + ◀ 返回待机 开餐中 · 午餐 2026-08-10 周一
@@ -525,26 +659,40 @@ - - + + + + diff --git a/web-admin/nutrition/prod-proc-serve.html b/web-admin/nutrition/prod-proc-serve.html index 8519cfe..047f394 100644 --- a/web-admin/nutrition/prod-proc-serve.html +++ b/web-admin/nutrition/prod-proc-serve.html @@ -116,6 +116,27 @@ tbody tr:hover td.td-actions{background:#F8FBFF;} .drawer-field{display:flex;flex-direction:column;gap:2px;} .drawer-field__label{font-size:var(--font-xs);color:var(--text-placeholder);} .drawer-field__value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;min-height:22px;} +/* 上餐重量单元格 - 蓝色可点击 */ +.serve-weight{display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:var(--primary);font-size:var(--font-sm);} +.serve-weight:hover{color:#40a9ff;} +/* 上餐记录弹窗 - 时间线 */ +.serve-log__summary{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:20px;} +.serve-log__summary-item{background:#FAFBFC;border:1px solid #F0F0F0;border-radius:6px;padding:12px 16px;} +.serve-log__summary-label{font-size:var(--font-xs);color:var(--text-placeholder);margin-bottom:4px;} +.serve-log__summary-value{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);} +.serve-log__summary-value .unit{font-size:var(--font-xs);color:var(--text-secondary);font-weight:400;margin-left:2px;} +.serve-log__list{position:relative;padding-left:24px;} +.serve-log__list::before{content:'';position:absolute;left:7px;top:8px;bottom:8px;width:2px;background:#E8E8E8;} +.serve-log__item{position:relative;padding:10px 0 10px 8px;} +.serve-log__item::before{content:'';position:absolute;left:-21px;top:14px;width:12px;height:12px;border-radius:50%;background:#fff;border:2px solid var(--primary);} +.serve-log__item--first::before{border-color:var(--success);background:var(--success);} +.serve-log__item--extra::before{border-color:var(--warning);background:var(--warning);} +.serve-log__head{display:flex;align-items:center;gap:8px;margin-bottom:6px;} +.serve-log__time{font-size:var(--font-sm);font-weight:600;color:var(--text-primary);} +.serve-log__fields{display:grid;grid-template-columns:repeat(4,1fr);gap:8px 16px;padding:8px 12px;background:#FAFBFC;border-radius:6px;} +.serve-log__field-label{font-size:var(--font-xs);color:var(--text-placeholder);} +.serve-log__field-value{font-size:var(--font-sm);color:var(--text-primary);font-weight:500;margin-top:2px;} +.serve-log__field-value--highlight{color:var(--warning);} @@ -160,11 +181,11 @@ tbody tr:hover td.td-actions{background:#F8FBFF;} - - - - - + + + + +
送达餐线餐次送达设备(秤台)识别方式菜品名称当前余量(kg)上餐重量(kg)出锅时间送达餐线时间上餐状态烹制任务号出锅温度(℃)厨师操作
A区中餐线午餐00025号秤🤖 自动识别宫保鸡丁12.538.211:1811:30上餐完成COOK-00182张厨师食材溯源链路 查看视频 更多 ▾
A区中餐线午餐00025号秤🤖 自动识别番茄炒蛋8.322.611:2011:30上餐完成COOK-00278李厨师食材溯源链路 查看视频 更多 ▾
B区中餐线午餐00027号秤👤 人工选择红烧肉1.242.611:2211:38余量不足COOK-00386王厨师食材溯源链路 查看视频 更多 ▾
A区早餐线早餐00022号秤🤖 自动识别小米粥012.607:2007:28上餐完成COOK-00675赵厨师食材溯源链路 查看视频 更多 ▾
B区早餐线早餐00023号秤👤 人工选择燕麦粥2.18.407:2207:35上餐完成COOK-00772陈厨师食材溯源链路 查看视频 更多 ▾
A区中餐线午餐00025号秤🤖 自动识别宫保鸡丁12.538.211:1811:30上餐完成COOK-00182张厨师食材溯源链路 查看视频 更多 ▾
A区中餐线午餐00025号秤🤖 自动识别番茄炒蛋8.322.611:2011:30上餐完成COOK-00278李厨师食材溯源链路 查看视频 更多 ▾
B区中餐线午餐00027号秤👤 人工选择红烧肉1.242.611:2211:38余量不足COOK-00386王厨师食材溯源链路 查看视频 更多 ▾
A区早餐线早餐00022号秤🤖 自动识别小米粥012.607:2007:28上餐完成COOK-00675赵厨师食材溯源链路 查看视频 更多 ▾
B区早餐线早餐00023号秤👤 人工选择燕麦粥2.18.407:2207:35上餐完成COOK-00772陈厨师食材溯源链路 查看视频 更多 ▾
C区快餐线午餐00028号秤👤 人工选择蒜蓉菠菜待上餐COOK-005食材溯源链路 查看视频 更多 ▾
@@ -248,6 +269,38 @@ tbody tr:hover td.td-actions{background:#F8FBFF;} + + + diff --git a/web-admin/nutrition/sup-clean-external.html b/web-admin/nutrition/sup-clean-external.html index 44dc90a..356333f 100644 --- a/web-admin/nutrition/sup-clean-external.html +++ b/web-admin/nutrition/sup-clean-external.html @@ -211,7 +211,7 @@ function toggleSubgroup(header) {
- +
订单号客户名称净菜类型菜品种类总份数总计量(kg)订单金额下单时间预定配送物流单号订单状态操作订单号客户名称净菜类型菜品种类总份数总计量(kg)订单金额下单时间订单状态预定配送物流信息操作
@@ -260,16 +260,92 @@ function toggleSubgroup(header) {
- + @@ -349,6 +407,22 @@ tbody tr:hover td.td-actions{background:#F8FBFF;} + + +
+
+
+
+ +
+
+ +
+ + +
+
+
@@ -496,7 +570,32 @@ function showWhDetail(el){ Drawer.open('仓库详情 — '+g(1),html); } -/* 区域管理详情 */ +/* 区域放置物品 Mock 数据:按区域编号索引,同一区域可同时存放多种净菜/毛菜 */ +var ZONE_ITEMS={ + 'WH-A-01':[ + {itemType:'毛菜',itemName:'菠菜',inOrder:'IN-20260415-001',inTime:'2026-04-15 10:30',op:'张仓管'}, + {itemType:'毛菜',itemName:'油麦菜',inOrder:'IN-20260415-012',inTime:'2026-04-15 11:10',op:'张仓管'} + ], + 'WH-A-02':[ + {itemType:'毛菜',itemName:'小白菜',inOrder:'IN-20260416-008',inTime:'2026-04-16 08:20',op:'张仓管'} + ], + 'WH-A-03':[ + {itemType:'毛菜',itemName:'胡萝卜',inOrder:'IN-20260416-005',inTime:'2026-04-16 11:00',op:'张仓管'}, + {itemType:'毛菜',itemName:'白萝卜',inOrder:'IN-20260416-006',inTime:'2026-04-16 11:20',op:'张仓管'} + ], + 'WH-B-01':[ + {itemType:'净菜',itemName:'净猪肉丁',inOrder:'IN-20260415-021',inTime:'2026-04-15 14:00',op:'王仓管'}, + {itemType:'毛菜',itemName:'五花肉',inOrder:'IN-20260415-020',inTime:'2026-04-15 13:30',op:'王仓管'} + ], + 'WH-B-02':[ + {itemType:'净菜',itemName:'净鸡腿肉',inOrder:'IN-20260415-025',inTime:'2026-04-15 15:00',op:'王仓管'} + ], + 'WH-C-01':[ + {itemType:'毛菜',itemName:'草鱼',inOrder:'IN-20260415-004',inTime:'2026-04-15 09:45',op:'李仓管'} + ] +}; + +/* 区域管理详情:使用中状态追加「当前放置物品」分区(净菜/毛菜可共存) */ function showZoneDetail(el){ var row=el.closest('tr'); var cells=row.querySelectorAll('td'); @@ -510,8 +609,336 @@ function showZoneDetail(el){ +'
容量(㎥)'+g(4)+'
' +'
状态'+h(5)+'
' +''; + /* 仅当状态为「使用中」时,展示当前放置物品列表 */ + var statusText=g(5); + if(statusText.indexOf('使用中')!==-1){ + var zoneCode=g(0); + var items=ZONE_ITEMS[zoneCode]||[]; + html+='
当前放置物品共 '+items.length+' 种
'; + if(items.length===0){ + html+='
暂无物品数据
'; + }else{ + html+='
' + +'' + +'' + +'' + +'' + +'' + +'' + +''; + items.forEach(function(it){ + var typeTag=it.itemType==='净菜'?'净菜':'毛菜'; + html+='' + +'' + +'' + +'' + +'' + +'' + +''; + }); + html+='
物品类型物品名称入库单号入库时间操作人
'+typeTag+''+it.itemName+''+it.inOrder+''+it.inTime+''+it.op+'
'; + } + } Drawer.open('区域详情 — '+g(1),html); } + +/* ====================== 智能货柜(Tab4)====================== */ +/* 智能货柜 Mock 数据:来自「设备管理」模块录入,此处只读展示 + 格口状态归并为:occupied(储物中) / idle(空闲) / offline(设备离线) */ +var CABINETS=[ + { + code:'CAB-NC-001',name:'3号净菜柜',cabinetType:'净菜柜',status:'在线',totalSlots:10, + slots:[ + {id:'NC3-01',status:'occupied',itemName:'净土豆丝',itemType:'净菜',qty:10.2,op:'张厨师',inTime:'2026-04-22 09:15'}, + {id:'NC3-02',status:'occupied',itemName:'净胡萝卜',itemType:'净菜',qty:15.6,op:'李主管',inTime:'2026-04-22 09:20'}, + {id:'NC3-03',status:'occupied',itemName:'净香菇',itemType:'净菜',qty:6.8,op:'王厨师',inTime:'2026-04-22 09:30'}, + {id:'NC3-04',status:'occupied',itemName:'净西兰花',itemType:'净菜',qty:8.5,op:'张厨师',inTime:'2026-04-22 09:40'}, + {id:'NC3-05',status:'occupied',itemName:'净白菜',itemType:'净菜',qty:18.0,op:'王厨师',inTime:'2026-04-22 08:50'}, + {id:'NC3-06',status:'idle'}, + {id:'NC3-07',status:'idle'}, + {id:'NC3-08',status:'idle'}, + {id:'NC3-09',status:'idle'}, + {id:'NC3-10',status:'idle'} + ] + }, + { + code:'CAB-NC-002',name:'5号净菜柜',cabinetType:'净菜柜',status:'在线',totalSlots:10, + slots:[ + {id:'NC5-01',status:'occupied',itemName:'净黄瓜片',itemType:'净菜',qty:7.4,op:'李主管',inTime:'2026-04-22 10:05'}, + {id:'NC5-02',status:'occupied',itemName:'净西红柿',itemType:'净菜',qty:12.0,op:'张厨师',inTime:'2026-04-22 10:15'}, + {id:'NC5-03',status:'occupied',itemName:'净洋葱',itemType:'净菜',qty:3.2,op:'王厨师',inTime:'2026-04-22 08:40'}, + {id:'NC5-04',status:'occupied',itemName:'净青椒丝',itemType:'净菜',qty:6.6,op:'张厨师',inTime:'2026-04-22 11:00'}, + {id:'NC5-05',status:'occupied',itemName:'净豆角',itemType:'净菜',qty:9.0,op:'李主管',inTime:'2026-04-22 11:10'}, + {id:'NC5-06',status:'occupied',itemName:'净藕片',itemType:'净菜',qty:4.8,op:'王厨师',inTime:'2026-04-22 11:20'}, + {id:'NC5-07',status:'idle'}, + {id:'NC5-08',status:'idle'}, + {id:'NC5-09',status:'idle'}, + {id:'NC5-10',status:'idle'} + ] + }, + { + code:'CAB-RW-008',name:'8号毛菜柜',cabinetType:'毛菜柜',status:'在线',totalSlots:8, + slots:[ + {id:'RW8-A1',status:'occupied',itemName:'菠菜',itemType:'毛菜',qty:225.0,op:'张仓管',inTime:'2026-04-15 10:30'}, + {id:'RW8-A2',status:'occupied',itemName:'油麦菜',itemType:'毛菜',qty:60.0,op:'张仓管',inTime:'2026-04-15 11:10'}, + {id:'RW8-B1',status:'occupied',itemName:'小白菜',itemType:'毛菜',qty:80.0,op:'张仓管',inTime:'2026-04-16 08:20'}, + {id:'RW8-B2',status:'occupied',itemName:'生菜',itemType:'毛菜',qty:42.5,op:'张仓管',inTime:'2026-04-16 09:00'}, + {id:'RW8-B3',status:'occupied',itemName:'空心菜',itemType:'毛菜',qty:30.0,op:'张仓管',inTime:'2026-04-15 08:30'}, + {id:'RW8-C1',status:'occupied',itemName:'芹菜',itemType:'毛菜',qty:12.0,op:'张仓管',inTime:'2026-04-14 16:00'}, + {id:'RW8-C2',status:'idle'}, + {id:'RW8-C3',status:'idle'} + ] + }, + { + code:'CAB-RW-009',name:'9号毛菜柜',cabinetType:'毛菜柜',status:'离线',totalSlots:8, + slots:[ + {id:'RW9-A1',status:'offline',itemName:'蒜薹',itemType:'毛菜',qty:55.0,op:'张仓管',inTime:'2026-04-15 14:00'}, + {id:'RW9-A2',status:'offline',itemName:'韭菜',itemType:'毛菜',qty:38.0,op:'张仓管',inTime:'2026-04-15 14:20'}, + {id:'RW9-B1',status:'offline'}, + {id:'RW9-B2',status:'offline'}, + {id:'RW9-C1',status:'offline'}, + {id:'RW9-C2',status:'offline'}, + {id:'RW9-C3',status:'offline'}, + {id:'RW9-D1',status:'offline'} + ] + } +]; + +/* 格口状态 → 文案/样式映射 */ +function slotStatusText(s){ + return {occupied:'储物中',idle:'空闲',offline:'离线'}[s]||s; +} +function slotStatusTag(s){ + var map={occupied:'tag-green',idle:'tag-gray',offline:'tag-gray'}; + return ''+slotStatusText(s)+''; +} + +/* 渲染智能货柜整行卡片列表 */ +function renderCabinets(){ + var wrap=document.getElementById('cabinetList'); + if(!wrap)return; + var html=''; + CABINETS.forEach(function(cab,idx){ + var statusTag=cab.status==='在线'?'● 在线' + :cab.status==='离线'?'● 离线' + :'● 故障'; + var typeTag=cab.cabinetType==='净菜柜'?'净菜柜':'毛菜柜'; + /* 统计:空闲 / 储物中 / 离线 格口数 */ + var idleCount=cab.slots.filter(function(s){return s.status==='idle';}).length; + var occupiedCount=cab.slots.filter(function(s){return s.status==='occupied';}).length; + var offlineCount=cab.slots.filter(function(s){return s.status==='offline';}).length; + /* 格口横向一行 */ + var cellsHtml=''; + cab.slots.forEach(function(s,sidx){ + var cls='cabinet-cell '+s.status; + var inner=''; + if(s.status==='idle'){ + inner='
'+s.id+'
空闲
'; + }else if(s.status==='offline'){ + inner='
'+s.id+'
'+(s.itemName||'—')+'
离线
'; + }else{ + inner='
'+s.id+'
' + +'
'+s.itemName+'
' + +'
'+s.qty+'kg
'; + } + cellsHtml+='
'+inner+'
'; + }); + html+='
' + +'
' + +''+cab.name+'' + +''+cab.code+'' + +'·' + +'共 '+cab.totalSlots+' 格口' + +'·' + +''+idleCount+' 空闲' + +''+occupiedCount+' 储物中' + +(offlineCount>0?'·'+offlineCount+' 离线':'') + +'
'+typeTag+statusTag+'
' + +'
' + +'
' + +'
'+cellsHtml+'
' + +'
' + +'
'; + }); + wrap.innerHTML=html; +} +renderCabinets(); + +/* 轻量 toast(不依赖其他组件) */ +function cabToast(msg){ + var old=document.getElementById('cabToast'); + if(old)old.remove(); + var t=document.createElement('div'); + t.id='cabToast'; + t.textContent=msg; + t.style.cssText='position:fixed;top:80px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,.78);color:#fff;padding:10px 20px;border-radius:6px;font-size:14px;z-index:3000;box-shadow:0 4px 12px rgba(0,0,0,.2);'; + document.body.appendChild(t); + setTimeout(function(){if(t)t.remove();},2200); +} + +/* 格口历史记录 Mock:键格式「柜编号|格口号」 */ +var SLOT_HISTORY={ + 'CAB-NC-001|NC3-01':[ + {time:'2026-04-22 14:20',itemType:'净菜',itemName:'净土豆丝',type:'取出',before:11.0,after:10.2,op:'王厨师',inOrder:'IN-20260415-001',remark:'做土豆丝炒肉'}, + {time:'2026-04-22 11:30',itemType:'净菜',itemName:'净土豆丝',type:'取出',before:11.8,after:11.0,op:'李主管',inOrder:'IN-20260415-001',remark:'做宫保鸡丁'}, + {time:'2026-04-22 09:15',itemType:'净菜',itemName:'净土豆丝',type:'存入',before:0.0,after:12.5,op:'张厨师',inOrder:'IN-20260415-001',remark:'首次入柜'} + ], + 'CAB-NC-001|NC3-02':[ + {time:'2026-04-22 15:40',itemType:'净菜',itemName:'净胡萝卜',type:'取出',before:16.8,after:15.6,op:'王厨师',inOrder:'IN-20260415-002',remark:'做胡萝卜炒肉'}, + {time:'2026-04-22 09:20',itemType:'净菜',itemName:'净胡萝卜',type:'存入',before:0.0,after:18.0,op:'李主管',inOrder:'IN-20260415-002',remark:'首次入柜'} + ], + 'CAB-NC-001|NC3-03':[ + {time:'2026-04-22 16:10',itemType:'净菜',itemName:'净香菇',type:'取出',before:7.5,after:6.8,op:'张厨师',inOrder:'IN-20260415-018',remark:'做香菇青菜'}, + {time:'2026-04-22 14:00',itemType:'净菜',itemName:'净香菇',type:'取出',before:8.2,after:7.5,op:'张厨师',inOrder:'IN-20260415-018',remark:'做香菇青菜'}, + {time:'2026-04-22 09:30',itemType:'净菜',itemName:'净香菇',type:'存入',before:0.0,after:9.0,op:'王厨师',inOrder:'IN-20260415-018',remark:'首次入柜'} + ], + 'CAB-NC-001|NC3-04':[ + {time:'2026-04-22 15:30',itemType:'净菜',itemName:'净西兰花',type:'取出',before:9.0,after:8.5,op:'李主管',inOrder:'IN-20260415-022',remark:'做西兰花炒虾仁'}, + {time:'2026-04-22 09:40',itemType:'净菜',itemName:'净西兰花',type:'存入',before:0.0,after:10.0,op:'张厨师',inOrder:'IN-20260415-022',remark:'首次入柜'} + ], + 'CAB-NC-001|NC3-05':[ + {time:'2026-04-22 11:10',itemType:'净菜',itemName:'净白菜',type:'取出',before:18.7,after:18.0,op:'王厨师',inOrder:'IN-20260415-006',remark:'取样检测'}, + {time:'2026-04-21 17:30',itemType:'净菜',itemName:'净白菜',type:'取出',before:20.5,after:18.7,op:'李主管',inOrder:'IN-20260415-006',remark:'晚餐备菜'}, + {time:'2026-04-20 09:30',itemType:'净菜',itemName:'净白菜',type:'取出',before:22.5,after:20.5,op:'张厨师',inOrder:'IN-20260415-006',remark:'午餐备菜'}, + {time:'2026-04-18 14:30',itemType:'净菜',itemName:'净白菜',type:'存入',before:0.0,after:23.0,op:'王厨师',inOrder:'IN-20260415-006',remark:'首次入柜'} + ], + 'CAB-NC-002|NC5-01':[ + {time:'2026-04-22 13:20',itemType:'净菜',itemName:'净黄瓜片',type:'取出',before:8.0,after:7.4,op:'李主管',inOrder:'IN-20260416-031',remark:'凉拌黄瓜'}, + {time:'2026-04-22 10:05',itemType:'净菜',itemName:'净黄瓜片',type:'存入',before:0.0,after:9.5,op:'李主管',inOrder:'IN-20260416-031',remark:'首次入柜'} + ], + 'CAB-NC-002|NC5-02':[ + {time:'2026-04-22 12:00',itemType:'净菜',itemName:'净西红柿',type:'取出',before:13.5,after:12.0,op:'张厨师',inOrder:'IN-20260416-032',remark:'西红柿炒蛋'}, + {time:'2026-04-22 10:15',itemType:'净菜',itemName:'净西红柿',type:'存入',before:0.0,after:15.0,op:'张厨师',inOrder:'IN-20260416-032',remark:'首次入柜'} + ], + 'CAB-NC-002|NC5-03':[ + {time:'2026-04-22 15:00',itemType:'净菜',itemName:'净洋葱',type:'取出',before:3.8,after:3.2,op:'王厨师',inOrder:'IN-20260416-033',remark:'洋葱炒蛋'}, + {time:'2026-04-22 08:40',itemType:'净菜',itemName:'净洋葱',type:'存入',before:0.0,after:5.0,op:'王厨师',inOrder:'IN-20260416-033',remark:'首次入柜'} + ], + 'CAB-RW-008|RW8-A1':[ + {time:'2026-04-16 09:00',itemType:'毛菜',itemName:'菠菜',type:'取出',before:248.0,after:225.0,op:'张仓管',inOrder:'IN-20260415-001',remark:'净菜加工领用'}, + {time:'2026-04-15 10:30',itemType:'毛菜',itemName:'菠菜',type:'存入',before:0.0,after:286.0,op:'张仓管',inOrder:'IN-20260415-001',remark:'毛菜入库'} + ], + 'CAB-RW-008|RW8-C1':[ + {time:'2026-04-16 08:00',itemType:'毛菜',itemName:'芹菜',type:'取出',before:18.0,after:12.0,op:'张仓管',inOrder:'IN-20260414-009',remark:'领用加工'} + ] +}; + +/* 格口历史居中大弹窗组件(1100×80vh) */ +var HistoryModal={ + open:function(title,bodyHtml,footerHtml){ + this.close(); + var mask=document.createElement('div'); + mask.className='history-modal-mask'; + var html='
' + +'
'+title+'
' + +'
' + +'
'+bodyHtml+'
'; + if(footerHtml){html+='';} + html+='
'; + mask.innerHTML=html; + mask.addEventListener('click',function(e){if(e.target===mask)HistoryModal.close();}); + document.body.appendChild(mask); + this._escHandler=function(e){if(e.key==='Escape')HistoryModal.close();}; + document.addEventListener('keydown',this._escHandler); + }, + close:function(){ + var m=document.querySelector('.history-modal-mask'); + if(!m)return; + m.classList.add('closing'); + setTimeout(function(){m.remove();},200); + if(this._escHandler){document.removeEventListener('keydown',this._escHandler);this._escHandler=null;} + } +}; + +/* 点击格口:弹出居中历史弹窗(上半区格口信息+存储详情,下半区历史取用记录) */ +var SLOT_HIST_CURRENT={cabIdx:0,slotIdx:0,key:'',page:1}; +var SLOT_HIST_PAGE_SIZE=6; +function showSlotHistory(cabIdx,slotIdx){ + var cab=CABINETS[cabIdx]; + if(!cab)return; + var slot=cab.slots[slotIdx]; + if(!slot)return; + /* 离线格口不响应 */ + if(slot.status==='offline'){ + cabToast('「'+cab.name+' · '+slot.id+'」设备离线,暂不可查看'); + return; + } + SLOT_HIST_CURRENT={cabIdx:cabIdx,slotIdx:slotIdx,key:cab.code+'|'+slot.id,page:1}; + /* 上半区:格口信息 + 当前存储详情 */ + var typeTag=cab.cabinetType==='净菜柜'?'净菜柜':'毛菜柜'; + var statusTag=cab.status==='在线'?'在线':cab.status==='离线'?'离线':'故障'; + var slotTypeTag=slot.itemType?(slot.itemType==='净菜'?'净菜':'毛菜'):'—'; + var infoHtml='
' + +'
所属柜:'+cab.name+'
' + +'
设备编号:'+cab.code+'
' + +'
货柜类型:'+typeTag+'
' + +'
设备状态:'+statusTag+'
' + +'
格口号:'+slot.id+'
' + +'
格口状态:'+slotStatusTag(slot.status)+'
' + +'
'; + /* 当前存储详情卡片(仅占用格口有数据) */ + var storeHtml=''; + if(slot.status==='occupied'){ + storeHtml='
' + +'
当前存储详情
' + +'
' + +'
物品类型'+slotTypeTag+'
' + +'
物品名称'+slot.itemName+'
' + +'
余量(kg)'+slot.qty+'
' + +'
操作人'+slot.op+'
' + +'
存入时间'+slot.inTime+'
' + +'
'; + }else{ + storeHtml='
该格口当前为空闲状态,暂无存储物品
'; + } + HistoryModal.open('格口历史记录 — '+slot.id, infoHtml+storeHtml+'
', '
'); + renderSlotHistoryPage(); +} + +function renderSlotHistoryPage(){ + var wrap=document.getElementById('slotHistTableWrap'); + var footer=document.getElementById('slotHistFooterWrap'); + if(!wrap)return; + var rows=(SLOT_HISTORY[SLOT_HIST_CURRENT.key]||[]).slice().sort(function(a,b){return b.time.localeCompare(a.time);}); + var total=rows.length; + var totalPages=Math.max(1,Math.ceil(total/SLOT_HIST_PAGE_SIZE)); + if(SLOT_HIST_CURRENT.page>totalPages)SLOT_HIST_CURRENT.page=totalPages; + if(SLOT_HIST_CURRENT.page<1)SLOT_HIST_CURRENT.page=1; + var start=(SLOT_HIST_CURRENT.page-1)*SLOT_HIST_PAGE_SIZE; + var pageRows=rows.slice(start,start+SLOT_HIST_PAGE_SIZE); + var html='
历史取用记录
'; + html+='
' + +'' + +''; + if(pageRows.length===0){ + html+=''; + }else{ + pageRows.forEach(function(r){ + var delta=Math.abs(r.after-r.before).toFixed(1); + var isPos=r.type==='存入'; + var deltaHtml=''+(isPos?'+':'-')+delta+' '+(isPos?'↑':'↓')+''; + var typeHtml=r.type==='存入'?'存入':'取出'; + var itemTypeHtml=r.itemType==='净菜'?'净菜':'毛菜'; + html+=''; + }); + } + html+='
操作时间物品类型物品名称操作类型操作前(kg)操作后(kg)余量变化操作人入库单号备注
该格口暂无历史记录
'+r.time+''+itemTypeHtml+''+r.itemName+''+typeHtml+''+r.before.toFixed(1)+''+r.after.toFixed(1)+''+deltaHtml+''+r.op+''+r.inOrder+''+(r.remark||'—')+'
'; + wrap.innerHTML=html; + if(footer){ + var pgHtml='
共 '+total+' 条'; + pgHtml+=''; + for(var i=1;i<=totalPages;i++){ + pgHtml+=''; + } + pgHtml+=''; + pgHtml+='
'; + footer.innerHTML=pgHtml; + } +} +function goSlotHistPage(p){ + SLOT_HIST_CURRENT.page=p; + renderSlotHistoryPage(); +}