diff --git a/.idea/claudeCodeTabState.xml b/.idea/claudeCodeTabState.xml
index 7b43906..ad4b3bd 100644
--- a/.idea/claudeCodeTabState.xml
+++ b/.idea/claudeCodeTabState.xml
@@ -7,9 +7,33 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -17,6 +41,6 @@
-
+
\ No newline at end of file
diff --git a/other-module/canteen-device/canteen-nutrition-scale/02-dish-display.html b/other-module/canteen-device/canteen-nutrition-scale/02-dish-display.html
index 6bc4f84..59d0068 100644
--- a/other-module/canteen-device/canteen-nutrition-scale/02-dish-display.html
+++ b/other-module/canteen-device/canteen-nutrition-scale/02-dish-display.html
@@ -175,6 +175,305 @@
visibility: visible;
transform: translateX(-50%) translateY(0);
}
+
+ /* ---- 演示模式切换按钮(仅原型演示,右上角简洁 pill) ---- */
+ .mode-switch {
+ position: absolute;
+ top: 20px;
+ right: 56px;
+ display: flex;
+ height: 22px;
+ background: rgba(255,255,255,0.06);
+ border: 1px solid rgba(255,255,255,0.12);
+ border-radius: 6px;
+ overflow: hidden;
+ z-index: 10;
+ }
+ .mode-switch::before {
+ content: '演示';
+ position: absolute;
+ left: -36px;
+ top: 50%;
+ transform: translateY(-50%);
+ font-size: 10px;
+ color: rgba(255,255,255,0.3);
+ letter-spacing: 1px;
+ }
+ .mode-switch button {
+ padding: 0 12px;
+ font-size: 11px;
+ color: rgba(255,255,255,0.5);
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ transition: all 0.2s;
+ height: 100%;
+ font-family: inherit;
+ }
+ .mode-switch button:hover {
+ background: rgba(255,255,255,0.06);
+ color: rgba(255,255,255,0.8);
+ }
+ .mode-switch button.active {
+ background: #FF9800;
+ color: #fff;
+ }
+
+ /* ---- 视频模式布局(纵向:上视频 + 下信息卡) ---- */
+ .video-mode {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ display: none;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 40px 60px 30px;
+ gap: 24px;
+ }
+ /* 视频模式激活时显示视频布局 */
+ .main-area.mode-video .video-mode {
+ display: flex;
+ }
+ /* 视频模式激活时隐藏常规模式的标题和菜品信息 */
+ .main-area.mode-video .center-heading,
+ .main-area.mode-video .dish-info {
+ display: none;
+ }
+
+ /* 视频播放器 */
+ .video-player {
+ width: 100%;
+ max-width: 680px;
+ aspect-ratio: 16 / 9;
+ border-radius: 12px;
+ overflow: hidden;
+ position: relative;
+ background: #000;
+ box-shadow: 0 12px 32px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.06);
+ }
+ .video-player .video-bg {
+ position: absolute;
+ top: 0; left: 0;
+ width: 100%; height: 100%;
+ }
+ .video-play-btn {
+ position: absolute;
+ top: 50%; left: 50%;
+ transform: translate(-50%, -50%);
+ width: 56px; height: 56px;
+ background: rgba(0,0,0,0.55);
+ border: 2px solid rgba(255,255,255,0.85);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ transition: transform 0.2s, background 0.2s;
+ z-index: 2;
+ }
+ .video-play-btn:hover {
+ background: rgba(0,0,0,0.75);
+ transform: translate(-50%, -50%) scale(1.05);
+ }
+ .video-play-btn::after {
+ content: '';
+ width: 0; height: 0;
+ border-left: 16px solid #fff;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ margin-left: 4px;
+ }
+ .video-controls {
+ position: absolute;
+ bottom: 0; left: 0; right: 0;
+ padding: 10px 14px;
+ background: linear-gradient(to top, rgba(0,0,0,0.75), transparent);
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ font-size: 11px;
+ color: rgba(255,255,255,0.85);
+ z-index: 2;
+ }
+ .video-progress {
+ flex: 1;
+ height: 3px;
+ background: rgba(255,255,255,0.2);
+ border-radius: 2px;
+ position: relative;
+ }
+ .video-progress::after {
+ content: '';
+ position: absolute;
+ left: 0; top: 0;
+ width: 35%;
+ height: 100%;
+ background: #FF9800;
+ border-radius: 2px;
+ }
+ .video-time {
+ font-size: 11px;
+ letter-spacing: 0.5px;
+ white-space: nowrap;
+ }
+ .video-fullscreen {
+ font-size: 13px;
+ cursor: pointer;
+ }
+
+ /* 信息卡 */
+ .video-info-card {
+ display: flex;
+ align-items: center;
+ gap: 28px;
+ padding: 14px 36px;
+ background: rgba(255,255,255,0.04);
+ border: 1px solid rgba(255,255,255,0.08);
+ border-radius: 12px;
+ }
+ .video-info-name {
+ font-size: 26px;
+ font-weight: 600;
+ color: #fff;
+ }
+ .video-info-divider {
+ width: 1px;
+ height: 28px;
+ background: rgba(255,255,255,0.15);
+ }
+ .video-info-item {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 4px;
+ }
+ .video-info-label {
+ font-size: 11px;
+ color: rgba(255,255,255,0.4);
+ letter-spacing: 1px;
+ }
+ .video-info-value {
+ font-size: 18px;
+ font-weight: 600;
+ color: #0AC4A8;
+ }
+ .video-info-unit {
+ font-size: 12px;
+ color: rgba(255,255,255,0.5);
+ font-weight: 400;
+ margin-left: 4px;
+ }
+
+ /* ---- 视频模式布局2(横向:左视频 + 右信息卡含标签) ---- */
+ .video-mode-h {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ display: none;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ padding: 40px 50px;
+ gap: 32px;
+ }
+ /* 视频2 模式激活时显示横向布局 */
+ .main-area.mode-video2 .video-mode-h {
+ display: flex;
+ }
+ /* 视频2 模式激活时隐藏常规元素与纵向视频布局 */
+ .main-area.mode-video2 .center-heading,
+ .main-area.mode-video2 .dish-info,
+ .main-area.mode-video2 .video-mode {
+ display: none;
+ }
+ /* 纵向视频模式激活时也隐藏横向布局 */
+ .main-area.mode-video .video-mode-h {
+ display: none;
+ }
+
+ /* 横向布局下的视频播放器(左侧,固定宽度) */
+ .video-mode-h .video-player {
+ flex: 0 0 auto;
+ width: 680px;
+ max-width: 60%;
+ }
+
+ /* 右侧信息卡(横向布局,纵向排列内容) */
+ .video-info-card-h {
+ flex: 1;
+ min-width: 280px;
+ max-width: 380px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 14px;
+ padding: 24px 28px;
+ background: rgba(255,255,255,0.04);
+ border: 1px solid rgba(255,255,255,0.08);
+ border-radius: 14px;
+ }
+ .video-info-name-h {
+ font-size: 28px;
+ font-weight: 600;
+ color: #fff;
+ line-height: 1.2;
+ }
+
+ /* 餐品标签 chips */
+ .video-tags-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ }
+ .video-tag-chip {
+ display: inline-flex;
+ align-items: center;
+ padding: 4px 10px;
+ font-size: 12px;
+ color: #0AC4A8;
+ background: rgba(10,196,168,0.12);
+ border: 1px solid rgba(10,196,168,0.25);
+ border-radius: 10px;
+ letter-spacing: 0.5px;
+ white-space: nowrap;
+ }
+ /* 标签色系变化(按位置循环,增加视觉层次) */
+ .video-tag-chip:nth-child(3n+2) {
+ color: #FF9800;
+ background: rgba(255,152,0,0.10);
+ border-color: rgba(255,152,0,0.25);
+ }
+ .video-tag-chip:nth-child(3n) {
+ color: #5B9BF8;
+ background: rgba(91,155,248,0.12);
+ border-color: rgba(91,155,248,0.25);
+ }
+
+ .video-info-divider-h {
+ width: 100%;
+ height: 1px;
+ background: rgba(255,255,255,0.12);
+ margin: 4px 0;
+ }
+ .video-info-item-h {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 6px;
+ width: 100%;
+ }
+ /* 横向布局右侧信息卡中的数值字号加大 */
+ .video-info-item-h .video-info-value {
+ font-size: 22px;
+ }
+ .video-info-item-h .video-info-label {
+ font-size: 12px;
+ }
@@ -185,6 +484,13 @@
◀ 返回 Phone-192.168.1.165:5555
+
+
+
+
+
+
+
⚙
@@ -212,6 +518,72 @@
点击菜品信息 → 进入开餐界面
+
+
+
+
+
+
+
+
+
+
+
+
⏯
+
+
01:23 / 03:45
+
⛶
+
+
+
+
+
宫保鸡丁
+
+
+ 单价
+ 5元/100克
+
+
+
+ 热量
+ 158.66千卡/100克
+
+
+
+
+
+
+
+
+
+
+
+
⏯
+
+
01:23 / 03:45
+
⛶
+
+
+
+
+
+
宫保鸡丁
+
+
+
+
+
+
+ 单价
+ 5元/100克
+
+
+
+ 每百克热量
+ 158.66千卡/100克
+
+
+
@@ -223,16 +595,16 @@
/* ===== 餐品数据映射(模拟后端) ===== */
var DISH_MAP = {
- 1: { name: '红烧肉', price: 5, kcal: 480, colors: ['#8B3A2A', '#D4764E', '#C05030'] },
- 2: { name: '宫保鸡丁', price: 5, kcal: 420, colors: ['#C87030', '#E8A040', '#D08028'] },
- 3: { name: '麻婆豆腐', price: 4, kcal: 280, colors: ['#706040', '#B89060', '#807050'] },
- 4: { name: '清炒时蔬', price: 3, kcal: 120, colors: ['#306028', '#50A040', '#408030'] },
- 5: { name: '香煎带鱼', price: 6, kcal: 320, colors: ['#805020', '#B88040', '#A06830'] },
- 6: { name: '糖醋排骨', price: 7, kcal: 520, colors: ['#802018', '#C05030', '#A03820'] },
- 7: { name: '蒜蓉西兰花', price: 3, kcal: 110, colors: ['#207040', '#40A868', '#308848'] },
- 8: { name: '米饭', price: 1.5, kcal: 260, colors: ['#D0D0C0', '#E8E8D8', '#E0E0C8'] },
- 9: { name: '紫菜蛋花汤', price: 2, kcal: 80, colors: ['#503028', '#805040', '#603830'] },
- 10: { name: '西红柿炒蛋', price: 4, kcal: 180, colors: ['#E8A030', '#F0C040', '#D89020'] }
+ 1: { name: '红烧肉', price: 5, kcal: 480, colors: ['#8B3A2A', '#D4764E', '#C05030'], tags: ['高蛋白', '高脂肪', '富含铁'] },
+ 2: { name: '宫保鸡丁', price: 5, kcal: 420, colors: ['#C87030', '#E8A040', '#D08028'], tags: ['高蛋白', '低芥酸', '营养均衡'] },
+ 3: { name: '麻婆豆腐', price: 4, kcal: 280, colors: ['#706040', '#B89060', '#807050'], tags: ['植物蛋白', '低芥酸', '微辣'] },
+ 4: { name: '清炒时蔬', price: 3, kcal: 120, colors: ['#306028', '#50A040', '#408030'], tags: ['低脂肪', '高纤维', '清淡'] },
+ 5: { name: '香煎带鱼', price: 6, kcal: 320, colors: ['#805020', '#B88040', '#A06830'], tags: ['高蛋白', '富含DHA', '低芥酸'] },
+ 6: { name: '糖醋排骨', price: 7, kcal: 520, colors: ['#802018', '#C05030', '#A03820'], tags: ['高蛋白', '高热量', '富含钙'] },
+ 7: { name: '蒜蓉西兰花', price: 3, kcal: 110, colors: ['#207040', '#40A868', '#308848'], tags: ['低脂肪', '高纤维', '富含维C'] },
+ 8: { name: '米饭', price: 1.5, kcal: 260, colors: ['#D0D0C0', '#E8E8D8', '#E0E0C8'], tags: ['主食', '低脂肪', '高碳水'] },
+ 9: { name: '紫菜蛋花汤', price: 2, kcal: 80, colors: ['#503028', '#805040', '#603830'], tags: ['低脂肪', '富含碘', '清淡'] },
+ 10: { name: '西红柿炒蛋', price: 4, kcal: 180, colors: ['#E8A030', '#F0C040', '#D89020'], tags: ['高蛋白', '低芥酸', '富含维C'] }
};
/* ===== 解析 URL 参数 ===== */
@@ -271,25 +643,34 @@
document.getElementById('dishPrice').textContent = dishData.price;
document.getElementById('dishKcal').textContent = dishData.kcal;
+ /* ===== 视频模式数据填充(纵向布局) ===== */
+ document.getElementById('videoDishName').textContent = dishData.name;
+ document.getElementById('videoDishPrice').textContent = dishData.price;
+ document.getElementById('videoDishKcal').textContent = dishData.kcal;
+ document.getElementById('videoBg').innerHTML = videoBgSVG(dishData.colors);
+
+ /* ===== 视频模式数据填充(横向布局,含标签) ===== */
+ document.getElementById('videoDishNameH').textContent = dishData.name;
+ document.getElementById('videoDishPriceH').textContent = dishData.price;
+ document.getElementById('videoDishKcalH').textContent = dishData.kcal;
+ document.getElementById('videoBgH').innerHTML = videoBgSVG(dishData.colors);
+ // 渲染餐品标签 chips
+ var tagsRow = document.getElementById('videoTagsRow');
+ var tagsHtml = '';
+ var dishTags = dishData.tags || [];
+ for (var i = 0; i < dishTags.length; i++) {
+ tagsHtml += '' + dishTags[i] + '';
+ }
+ tagsRow.innerHTML = tagsHtml;
+
/* ===== 点击菜品信息 → 进入开餐界面 ===== */
document.getElementById('dishInfo').addEventListener('click', function() {
window.location.href = '01-meal-start.html';
});
- /* ===== 模拟人脸识别(站在设备前自动触发) ===== */
- var faceDetectTimer = null;
+ /* ===== 演示说明:原 3 秒自动跳转逻辑已移除,改为用户主动点击菜品信息后跳转 ===== */
var isEmployee = false; // 02 默认买家态(买家身份进入)
- function startFaceDetect() {
- // 模拟:站在设备前 3 秒后识别成功
- faceDetectTimer = setTimeout(function() {
- // 识别成功 → 跳转取餐界面
- window.location.href = '03-meal-pickup.html?dishId=' + dishId;
- }, 3000);
- }
- // 页面加载后自动启动人脸识别
- startFaceDetect();
-
/* ===== Toast 提示 ===== */
var toastEl = document.getElementById('toast');
function showToast(msg, duration) {
@@ -311,6 +692,59 @@
}
window.location.href = '04-settings.html';
});
+
+ /* ===== 演示模式切换(常规 / 视频 / 视频2) ===== */
+ var modeSwitch = document.getElementById('modeSwitch');
+ var mainArea = document.querySelector('.main-area');
+ modeSwitch.addEventListener('click', function(e) {
+ var btn = e.target.closest('button[data-mode]');
+ if (!btn) return;
+ var mode = btn.getAttribute('data-mode');
+ // 切换按钮高亮状态
+ var btns = modeSwitch.querySelectorAll('button[data-mode]');
+ for (var i = 0; i < btns.length; i++) {
+ btns[i].classList.toggle('active', btns[i] === btn);
+ }
+ // 通过 main-area 的 class 控制布局切换:先清除所有模式类,再按需添加
+ mainArea.classList.remove('mode-video', 'mode-video2');
+ if (mode === 'video') {
+ mainArea.classList.add('mode-video');
+ } else if (mode === 'video2') {
+ mainArea.classList.add('mode-video2');
+ }
+ });
+
+ /* ===== 视频播放按钮(演示用,点击切换播放/暂停图标) ===== */
+ var videoPlaying = false;
+ function bindVideoPlayBtn(btnId) {
+ document.getElementById(btnId).addEventListener('click', function() {
+ videoPlaying = !videoPlaying;
+ this.style.opacity = videoPlaying ? '0' : '1';
+ });
+ }
+ bindVideoPlayBtn('videoPlayBtn');
+ bindVideoPlayBtn('videoPlayBtnH');
+
+ /* ===== 视频背景 SVG(按菜品色系生成展示画面) ===== */
+ function videoBgSVG(colors) {
+ var w = 680, h = 383; // 16:9 比例
+ var id = 'vidGrad';
+ return '';
+ }
diff --git a/other-module/canteen-device/canteen-nutrition-scale/doc/CHANGELOG.md b/other-module/canteen-device/canteen-nutrition-scale/doc/CHANGELOG.md
index 43c5421..82029e5 100644
--- a/other-module/canteen-device/canteen-nutrition-scale/doc/CHANGELOG.md
+++ b/other-module/canteen-device/canteen-nutrition-scale/doc/CHANGELOG.md
@@ -1,5 +1,19 @@
# 餐线营养秤 - 变更记录
+## [2026-08-05] feat: 菜品展示页新增视频演示模式
+
+### 新增
+- **演示模式切换按钮**(`02-dish-display.html`):右上角新增「演示」标识 + 模式切换 pill(常规 / 视频),默认常规模式
+- **视频模式布局**:纵向「上视频 + 下信息卡」布局,680px 宽 16:9 视频播放器,圆角阴影悬浮卡片
+- **视频播放器组件**:含视频背景、居中播放按钮、控制条(进度条 / 时间 / 音量 / 全屏)
+- **菜品信息卡**:视频下方展示菜品名、营养指标(热量 / 蛋白 / 脂肪 / 碳水)、简介描述
+- **模式联动**:视频模式激活时隐藏常规模式标题和菜品信息区,切换无闪烁
+
+### 调整
+- `02-dish-display.html` — `main-area` 增加 `mode-video` 状态类,通过 CSS 控制两种布局切换
+
+---
+
## [2026-07-27] feat: 设置页新增闭餐功能
### 新增
diff --git a/web-admin/nutrition/doc/CHANGELOG.md b/web-admin/nutrition/doc/CHANGELOG.md
index 5b06112..88b699e 100644
--- a/web-admin/nutrition/doc/CHANGELOG.md
+++ b/web-admin/nutrition/doc/CHANGELOG.md
@@ -1,5 +1,28 @@
# 营养用餐管理端 CHANGELOG
+## [2026-08-05] feat: 净菜订单/申领页面统一新增订单金额字段与总金额栏
+
+### 变更背景
+原净菜生产订单、外售订单、内供申领三页均无金额字段,仅在新增/编辑弹窗内展示「汇总预览」(净菜类型/菜品/包装规格/份数/计量)。为补齐订单金额闭环,统一在三页增加单价、小计、订单总金额字段。
+
+### 新增
+- **`prod-clean-order.html`**(净菜生产订单)
+ - 订单数据 `lines[]` 每项新增 `price`(单价)和 `subtotal`(小计)字段,覆盖内供/外售 6 个示例订单共 14 条明细
+ - 弹窗底部新增「订单总金额」栏,`#orderTotalAmount` 实时展示 `¥1,234.5` 格式金额
+ - 新增 `calcOrderTotal(o)` 与 `formatMoney(n)` 工具函数
+- **`sup-clean-external.html`**(外售订单)
+ - 表头新增「订单金额」列;订单明细新增 `price`/`subtotal` 字段(6 个示例订单 14 条明细)
+ - 弹窗移除「汇总预览」表格,改为底部「订单总金额」栏
+- **`sup-clean-internal.html`**(内供申领)
+ - 表头新增「订单金额」列;申领明细新增 `price`/`subtotal` 字段(5 个示例订单 11 条明细)
+ - 弹窗移除「汇总预览」表格,改为底部「订单总金额」栏
+
+### 调整
+- 三个页面弹窗的「汇总预览」表格(含 `orderSummary`/`extSummary`/`claimSummary` 容器与 thead/tbody)统一移除,改为弹窗 body 下方贴底的灰底总金额栏
+- 金额格式化统一走 `formatMoney(n)`:`¥1,234.5`(千分位 + 最多 2 位小数)
+
+---
+
## [2026-08-05] 规格体系统一化 · 阶段五辅助页改造(5.1~5.3 全部完成)
> 本次为 `规格体系统一化改造任务清单.md` 第五阶段辅助页 3 个任务(共 6 个文件)的统一改造。本阶段补齐了跨页共享的"写入端"、字典语义对齐和残余多形态字符串结构化,标志着规格体系统一化改造五个阶段全部完成。
diff --git a/web-admin/nutrition/prod-clean-order.html b/web-admin/nutrition/prod-clean-order.html
index 4fcd4f7..a0794f2 100644
--- a/web-admin/nutrition/prod-clean-order.html
+++ b/web-admin/nutrition/prod-clean-order.html
@@ -284,16 +284,12 @@ tr.detail-row td.td-actions{background:#FAFBFC;box-shadow:-4px 0 8px rgba(0,0,0,
-
-
-
汇总预览
-
- | 净菜类型 | 菜品/食材 | 包装规格 | 份数 | 计量(kg) |
-
-
-
+
+ 订单总金额:
+ ¥0
+