feat: 餐线营养秤双屏取餐页合并 + 收银设备全流程原型补齐

- 餐线营养秤:合并 dual-large/dual-small 两页为单页 03-meal-pickup-dual.html(左右双屏同页布局)
- 餐线营养秤:5 个二级页面(01/04/05/06/03)统一返回按钮 history.back() 兜底逻辑
- 餐线营养秤:02-dish-display 与 03-meal-pickup 样式重构(信息卡双行布局、菜品行价格靠右)
- 收银设备:新增 9 个收银员屏页面(01-login ~ 09-print-receipt,覆盖登录/待机/收银/支付成功/订单/详情/统计/对账/小票)
- 收银设备:新增 4 个用户屏页面(user-01-idle ~ user-04-success,覆盖待机/同步/支付/成功)
- 收银设备:index 重构为左右双屏(用户屏/收银员屏)布局
- 同步更新记忆索引、项目进度与 lint 报告

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
fengpu
2026-08-06 19:57:25 +08:00
co-authored by Claude Opus 4.7
parent a7e0e02945
commit 51661ab127
28 changed files with 9932 additions and 1403 deletions
+2 -2
View File
@@ -1,10 +1,10 @@
_Last synced: 2026-08-05 | Base commit: `d00208a`_
_Last synced: 2026-08-06 | Base commit: `445d824`_
# 记忆索引
| 文件 | 描述 | 类型 | 最后更新 |
|------|------|------|----------|
| project_overview.md | 项目技术栈、架构与模块结构 | project | 2026-05-14 |
| project_progress.md | 各模块原型开发进度 | project | 2026-08-05 |
| project_progress.md | 各模块原型开发进度 | project | 2026-08-06 |
| decisions.md | 关键设计决策与架构约定 | project | 2026-08-05 |
| feedback.md | 协作规范与用户纠正记录 | feedback | 2026-06-15 |
| user_profile.md | 用户角色与偏好 | user | 2026-04-21 |
+14 -9
View File
@@ -2,12 +2,12 @@
name: 记忆健康检查报告
description: memory-lint 最新一次执行的检查结果与待处理项
type: lint
last_updated: 2026-08-05
last_updated: 2026-08-06
---
# 记忆健康检查报告
> _执行时间: 2026-08-05 | Base commit: `d00208a` | Last synced: 2026-08-05_
> _执行时间: 2026-08-06 | Base commit: `445d824` | Last synced: 2026-08-06_
## 健康概览
@@ -18,11 +18,11 @@ last_updated: 2026-08-05
| 引用存在性检测(3A) | ✅ | 0 | 0 |
| 双链对称性检测(3B) | ✅ | 0 | 0 |
| 内容矛盾检测 | ✅ | — | 0 |
| 过期检测 | ⚠ | — | 2 待处理 |
| 过期检测 | ⚠ | — | 3 待处理 |
| 可推断内容污染 | ⚠ | — | 1 待处理 |
| frontmatter 完整性 | ⚠ | — | 4 待处理 |
**AUTO-FIX 已执行 0 项 | NEED-HUMAN 待处理 7**
**AUTO-FIX 已执行 0 项 | NEED-HUMAN 待处理 8**
---
@@ -30,18 +30,23 @@ last_updated: 2026-08-05
### [ERROR] 严重过期 — user_profile.md
- **文件**`user_profile.md`last_updated: 2026-04-21,距今 106 天,超过 90 天 ERROR 阈值)
- **文件**`user_profile.md`last_updated: 2026-04-21,距今 107 天,超过 90 天 ERROR 阈值)
- **建议**:确认用户角色/偏好是否有变化,执行 `/memory-update` 更新。
### [WARN] 过期 — feedback.md
- **文件**`feedback.md`last_updated: 2026-06-15,距今 51 天,超 30 天 WARN 阈值)
- **文件**`feedback.md`last_updated: 2026-06-15,距今 52 天,超 30 天 WARN 阈值)
- **建议**:确认是否有新的协作规范需要记录。
### [WARN] 过期 — project_overview.md
- **文件**`project_overview.md`last_updated: 2026-05-14,距今 84 天,超 30 天 WARN 阈值,临近 90 天 ERROR
- **建议**:确认项目技术栈/架构是否有变化需要同步。
### [WARN] 可推断内容污染 — project_progress.md
- **文件**`project_progress.md` 第 110~145 行「近期里程碑」区段
- **问题**:含具体文件路径列表(如 `canteen-nutrition-scale/02-dish-display.html``prod-clean-order`/`sup-clean-external`/`sup-clean-internal`)和 commit message 风格描述,按 memory-update 规则「Git 历史(可用 git log 查)」不应写入记忆文件
- **文件**`project_progress.md` 第 108~145 行「近期里程碑」区段
- **问题**:含具体文件路径列表(如 `canteen-nutrition-scale/02-dish-display.html``prod-clean-order`/`sup-clean-external`/`sup-clean-internal``din-ingredient-add.html`)和 commit message 风格描述,按 memory-update 规则「Git 历史(可用 git log 查)」不应写入记忆文件
- **建议**:保留里程碑结论,删除具体文件路径与 commit message 流水,让用户能通过 `git log` 自查细节。
### [WARN] frontmatter 缺失 — 4 个文件
@@ -60,4 +65,4 @@ last_updated: 2026-08-05
- `decisions.md#餐厅终端设备 PAD 居中外壳设计模式``[[feedback.md#PAD 终端页面内禁止可见滚动条]]` ✅ 目标存在,双向闭环
- `feedback.md#PAD 终端页面内禁止可见滚动条``[[decisions.md#餐厅终端设备 PAD 居中外壳设计模式]]` ✅ 目标存在,双向闭环
- `decisions.md#规格体系统一化改造``[[feedback.md]]` ✅ 目标存在(占位引用「暂无直接关联条目」)
- `decisions.md#规格体系统一化改造``[[feedback.md]]` ✅ 目标存在(占位引用「暂无直接关联条目」,非对称但属预期
+3 -2
View File
@@ -2,8 +2,8 @@
name: 项目进度
description: 各模块原型开发进度与里程碑
type: project
last_updated: 2026-08-05
commit: d00208a
last_updated: 2026-08-06
commit: 445d824
---
# 项目进度
@@ -105,6 +105,7 @@ Web 管理端和员工端 APP 的其余模块(系统管理、运动管理、
- 覆盖模块:18 个(含三端+其他终端)
## 近期里程碑
- 2026-08-06:食材档案新增「基础定价」字段 + 净菜订单按餐次核算人数与「生成中」状态(commit 445d824)——①`din-ingredient.html`/`din-ingredient-add.html` 食材档案新增 `basePrice` 字段(元/100g),列表详情区与新增/编辑/复制三形态同步(input 含「元/100g」内联单位后缀);②`prod-clean-order.html` 由食谱快速创建订单弹窗重构:移除顶部全局人数输入框与「订单汇总」预览区、当日食谱表格新增「就餐人数」列(每餐次独立 input 4 个)、新增预定配送时间字段(datetime-local,默认次日 10:00)、新增 `validateMealDinerCounts()` 校验、份数计算改为按各餐次人数累加、由食谱创建的订单 `lines[].status` 初始置为「生成中」;③新增「生成中」订单状态全链路:青色脉冲呼吸动效 `.tag-cyan` + `@keyframes statusPulse``aggregateStatus()` 聚合规则、状态筛选下拉、统计卡片、订单操作列「生成完成」入口(流转到「备货中」)、智能核算提示语 `.recipe-tip`。同日 `din-dish-add/all/own.html` 三页定价区继续微调(与 2026-08-05/06 定价区改造一脉相承)。
- 2026-08-05:餐线营养秤菜品展示页新增视频演示模式 + 净菜订单/申领三页统一订单金额字段(commit d00208a)——①`canteen-nutrition-scale/02-dish-display.html` 新增演示模式切换 pill(常规/视频)与视频模式布局(上视频+下信息卡,680px 16:9 视频播放器含播放按钮/控制条,下方菜品名+营养指标信息卡),通过 `main-area.mode-video` 状态类控制 CSS 布局切换;②`web-admin/nutrition` 净菜三页(`prod-clean-order`/`sup-clean-external`/`sup-clean-internal`)统一增加订单金额字段:订单明细 `lines[]` 每项新增 `price``subtotal` 字段、列表表头新增「订单金额」列、弹窗移除「汇总预览」表格改为底部灰底「订单总金额」栏(`#orderTotalAmount`/`#extTotalAmount`/`#claimTotalAmount`)、新增 `calcOrderTotal(o)``formatMoney(n)` 工具函数(`¥1,234.5` 千分位 + 最多 2 位小数)。
- 2026-08-05:规格体系统一化改造阶段四(设备端)+ 阶段五(辅助页)全部完成(commit 4fd44f1)——阶段四覆盖设备端 9 任务 14 文件:①毛菜验收秤 `verifyType` 字段(weight/count+ UNIT_OPTIONS 分类;②毛菜加工秤 4 页存储层斤→克、`formatGram` 展示层兼容、`yieldRate` 字段、04-history 语法错误修复;③净菜加工秤设置页删除"重量单位"select、滚刀块 cm→mm;④净菜包装贴标秤 3 页(最复杂)5 个工具函数内联、`cutSpec`/`packSpec` 全部结构化、`portions``packSize` 重命名;⑤净菜组配秤 3 页工具函数内联 + `localStorage['dish_specs_v1']` 跨页共享 + `resolvePackSpec` 兜底。阶段五覆盖辅助页 3 任务 6 文件:①营养质控 3 页(confirmSync 真落地写入餐品总库、菜品下拉跨页共享、同步日志驱动);②分析页字典语义修正(`sup-process-analysis` 切配线"切丝"→"丝"形状名词、新增独立 `pack_method` 字典;`sup-biz-analysis` 投料/产出吨→kg 对齐);③净菜进柜 `prod-proc-cabinet``spec` 多形态字符串结构化(含决策点 #10`'6份/箱'` 理解为 6 个份型单位装一箱)。新增权威源 `doc/spec-utils-reference.md`、改造任务清单与研发同步说明。阶段四+五完成标志着规格体系统一化五个阶段全部完成。
- 2026-08-05:体重管理新增 `eat-exercise-detail-v2.html`(饮食运动详情 v2);西安中心应急大屏迭代至 `index-v4.html`
+27 -4
View File
@@ -7,7 +7,7 @@
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="2a1427c6-520d-4da9-87a9-28e066647864" />
<option name="sessionId" value="502b97a5-c9e7-4eb8-b7fc-9567cb6a69da" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-7[1m]" />
<option name="permissionMode" value="bypassPermissions" />
@@ -19,7 +19,7 @@
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="916a3047-30c5-4f02-a0de-f2e2ba660d52" />
<option name="sessionId" value="6a9b0916-c45b-4c23-8e0c-f35ea3deee13" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-7[1m]" />
<option name="permissionMode" value="bypassPermissions" />
@@ -31,7 +31,30 @@
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="eb87e0d9-e045-4412-8eaa-bcecfed97b43" />
<option name="sessionId" value="55b6098e-8bc5-4fe4-ba55-1965903c9d6c" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-7[1m]" />
<option name="permissionMode" value="bypassPermissions" />
<option name="reasoningEffort" value="high" />
</TabSessionState>
</value>
</entry>
<entry key="3">
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-sonnet-4-6" />
<option name="permissionMode" value="bypassPermissions" />
<option name="reasoningEffort" value="high" />
</TabSessionState>
</value>
</entry>
<entry key="4">
<value>
<TabSessionState>
<option name="provider" value="claude" />
<option name="sessionId" value="2c735e9c-8739-48be-8864-ef433d7fc841" />
<option name="cwd" value="$PROJECT_DIR$" />
<option name="model" value="claude-opus-4-7[1m]" />
<option name="permissionMode" value="bypassPermissions" />
@@ -41,6 +64,6 @@
</entry>
</map>
</option>
<option name="tabCount" value="3" />
<option name="tabCount" value="5" />
</component>
</project>
@@ -522,6 +522,11 @@
</div>
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
/**
* 餐品数据库(模拟)
*/
@@ -48,85 +48,6 @@
position: relative;
}
/* 居中大标题 */
.center-heading {
position: absolute;
top: 60px;
left: 0;
right: 0;
text-align: center;
}
.big-text {
font-size: 56px;
font-weight: 700;
color: #FF9800;
letter-spacing: 6px;
text-shadow: 0 0 30px rgba(255,152,0,0.25), 0 2px 10px rgba(0,0,0,0.3);
}
/* 底部菜品信息 */
.dish-info {
position: absolute;
bottom: 60px;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
gap: 18px;
cursor: pointer;
padding: 16px 24px;
border-radius: 12px;
transition: background 0.2s;
}
.dish-info:hover {
background: rgba(74,144,217,0.08);
}
.dish-img-box {
width: 120px;
height: 90px;
border-radius: 10px;
overflow: hidden;
flex-shrink: 0;
box-shadow: 0 4px 16px rgba(0,0,0,0.5);
}
.dish-img-box svg {
width: 100%;
height: 100%;
}
.dish-info-text {
display: flex;
flex-direction: column;
gap: 8px;
}
.dish-name-row {
font-size: 32px;
font-weight: 600;
}
.dish-name-row .price-info {
font-size: 22px;
font-weight: 400;
color: rgba(255,255,255,0.7);
}
.dish-name-row .price-num {
color: #0AC4A8;
font-weight: 600;
}
.dish-cal-row {
font-size: 22px;
color: rgba(255,255,255,0.6);
}
.dish-cal-row .cal-num {
color: #0AC4A8;
font-weight: 600;
}
.dish-hint {
font-size: 12px;
color: rgba(255,255,255,0.25);
margin-top: 4px;
text-align: center;
}
/* ---- 设置按钮 ---- */
.settings-btn {
position: absolute;
@@ -200,7 +121,7 @@
letter-spacing: 1px;
}
.mode-switch button {
padding: 0 12px;
padding: 0 14px;
font-size: 11px;
color: rgba(255,255,255,0.5);
background: transparent;
@@ -219,40 +140,239 @@
color: #fff;
}
/* ---- 视频模式布局(纵向:上视频 + 信息卡) ---- */
.video-mode {
/* ================ 常规模式布局(左右分栏:左大图 + 信息卡) ================ */
.normal-mode {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
top: 0; left: 0; right: 0; bottom: 0;
display: flex;
flex-direction: column;
padding: 50px 80px 30px;
}
/* 顶部副标题 */
.normal-heading {
text-align: center;
margin-bottom: 24px;
}
.normal-heading__text {
font-size: 26px;
font-weight: 600;
color: #FF9800;
letter-spacing: 4px;
text-shadow: 0 0 20px rgba(255,152,0,0.2);
}
/* 中部左右分栏内容 */
.normal-content {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 60px 30px;
gap: 24px;
cursor: pointer;
transition: background 0.2s;
border-radius: 16px;
}
/* 视频模式激活时显示视频布局 */
.main-area.mode-video .video-mode {
.normal-content:hover {
background: rgba(74,144,217,0.05);
}
/* 左侧大图 */
.normal-img-box {
width: 480px;
height: 360px;
border-radius: 20px;
overflow: hidden;
flex-shrink: 0;
box-shadow: 0 16px 48px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.06);
}
.normal-img-box svg { width: 100%; height: 100%; }
/* 右侧信息卡 */
.normal-info {
display: flex;
flex-direction: column;
gap: 18px;
min-width: 380px;
max-width: 440px;
}
/* 视频模式激活时隐藏常规模式的标题和菜品信息 */
.main-area.mode-video .center-heading,
.main-area.mode-video .dish-info {
.normal-info__name {
font-size: 40px;
font-weight: 700;
color: #fff;
line-height: 1.2;
}
/* 价格突出显示 */
.normal-info__price {
display: flex;
align-items: baseline;
gap: 6px;
padding: 14px 20px;
background: linear-gradient(135deg, rgba(10,196,168,0.12), rgba(10,196,168,0.04));
border: 1px solid rgba(10,196,168,0.3);
border-radius: 12px;
width: fit-content;
}
.normal-info__price-symbol {
font-size: 24px;
font-weight: 600;
color: #0AC4A8;
}
.normal-info__price-num {
font-size: 56px;
font-weight: 800;
color: #0AC4A8;
line-height: 1;
text-shadow: 0 0 20px rgba(10,196,168,0.3);
}
.normal-info__price-unit {
font-size: 16px;
color: rgba(10,196,168,0.7);
font-weight: 400;
}
/* 餐品标签 chips */
.normal-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.dish-tag {
display: inline-flex;
align-items: center;
padding: 5px 12px;
font-size: 13px;
color: #0AC4A8;
background: rgba(10,196,168,0.12);
border: 1px solid rgba(10,196,168,0.25);
border-radius: 12px;
letter-spacing: 0.5px;
white-space: nowrap;
}
.dish-tag:nth-child(3n+2) {
color: #FF9800;
background: rgba(255,152,0,0.10);
border-color: rgba(255,152,0,0.25);
}
.dish-tag:nth-child(3n) {
color: #5B9BF8;
background: rgba(91,155,248,0.12);
border-color: rgba(91,155,248,0.25);
}
/* 分隔线 */
.normal-divider {
width: 100%;
height: 1px;
background: rgba(255,255,255,0.1);
margin: 4px 0;
}
/* 热量信息 */
.normal-cal {
display: flex;
align-items: baseline;
gap: 8px;
}
.normal-cal__label {
font-size: 14px;
color: rgba(255,255,255,0.5);
letter-spacing: 1px;
}
.normal-cal__num {
font-size: 28px;
font-weight: 700;
color: #fff;
}
.normal-cal__unit {
font-size: 13px;
color: rgba(255,255,255,0.5);
}
/* 底部进入提示 */
.normal-hint {
text-align: center;
font-size: 13px;
color: rgba(255,255,255,0.35);
margin-top: 16px;
letter-spacing: 1px;
}
/* 视频模式激活时隐藏常规布局 */
.main-area.mode-video .normal-mode {
display: none;
}
/* 视频播放器 */
.video-player {
width: 100%;
max-width: 680px;
aspect-ratio: 16 / 9;
/* ================ 视频模式布局(上信息条 + 下大视频) ================ */
.video-mode {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
display: none;
flex-direction: column;
padding: 24px 40px 28px;
gap: 20px;
}
.main-area.mode-video .video-mode {
display: flex;
}
/* 顶部信息条(菜名 + 价格突出 + 标签) */
.video-topbar {
display: flex;
align-items: center;
gap: 24px;
padding: 14px 24px;
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 12px;
flex-shrink: 0;
}
.video-topbar__name {
font-size: 32px;
font-weight: 700;
color: #fff;
flex-shrink: 0;
}
/* 视频模式价格突出(青底胶囊,靠右) */
.video-topbar__price {
display: flex;
align-items: baseline;
gap: 4px;
padding: 8px 18px;
background: linear-gradient(135deg, rgba(10,196,168,0.18), rgba(10,196,168,0.08));
border: 1px solid rgba(10,196,168,0.4);
border-radius: 10px;
flex-shrink: 0;
margin-left: auto;
}
.video-topbar__price-symbol {
font-size: 18px;
font-weight: 600;
color: #0AC4A8;
}
.video-topbar__price-num {
font-size: 36px;
font-weight: 800;
color: #0AC4A8;
line-height: 1;
text-shadow: 0 0 12px rgba(10,196,168,0.4);
}
.video-topbar__price-unit {
font-size: 13px;
color: rgba(10,196,168,0.7);
margin-left: 2px;
}
/* 视频模式标签行 */
.video-topbar__tags {
display: flex;
flex-wrap: wrap;
gap: 6px;
flex: 1;
min-width: 0;
}
/* 视频播放区(尽量放大) */
.video-player {
flex: 1;
width: 100%;
border-radius: 14px;
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);
box-shadow: 0 16px 40px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.06);
min-height: 0;
}
.video-player .video-bg {
position: absolute;
@@ -263,7 +383,7 @@
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 56px; height: 56px;
width: 64px; height: 64px;
background: rgba(0,0,0,0.55);
border: 2px solid rgba(255,255,255,0.85);
border-radius: 50%;
@@ -281,26 +401,26 @@
.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;
border-left: 18px solid #fff;
border-top: 12px solid transparent;
border-bottom: 12px solid transparent;
margin-left: 5px;
}
.video-controls {
position: absolute;
bottom: 0; left: 0; right: 0;
padding: 10px 14px;
padding: 12px 16px;
background: linear-gradient(to top, rgba(0,0,0,0.75), transparent);
display: flex;
align-items: center;
gap: 10px;
font-size: 11px;
gap: 12px;
font-size: 12px;
color: rgba(255,255,255,0.85);
z-index: 2;
}
.video-progress {
flex: 1;
height: 3px;
height: 4px;
background: rgba(255,255,255,0.2);
border-radius: 2px;
position: relative;
@@ -315,172 +435,20 @@
border-radius: 2px;
}
.video-time {
font-size: 11px;
font-size: 12px;
letter-spacing: 0.5px;
white-space: nowrap;
}
.video-fullscreen {
font-size: 13px;
font-size: 14px;
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;
}
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部窗口栏 -->
<div class="top-bar">
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a> <span>Phone-192.168.1.165:5555</span>
</div>
@@ -488,7 +456,6 @@
<div class="mode-switch" id="modeSwitch">
<button class="active" data-mode="normal">常规</button>
<button data-mode="video">视频</button>
<button data-mode="video2">视频2</button>
</div>
<!-- 设置按钮 -->
@@ -499,64 +466,62 @@
<!-- 主内容区 -->
<div class="main-area">
<!-- 中央大标题 -->
<div class="center-heading">
<div class="big-text">先识别 后取餐</div>
</div>
<!-- 底部菜品信息(点击进入开餐界面) -->
<div class="dish-info" id="dishInfo">
<div class="dish-img-box" id="dishImg"></div>
<div class="dish-info-text">
<div class="dish-name-row">
<span id="dishName">宫保鸡丁</span>
<span class="price-info">(单价 <span class="price-num" id="dishPrice">5</span> 元/100克)</span>
</div>
<div class="dish-cal-row">
热量 <span class="cal-num" id="dishKcal">158.66</span> 千卡/100克
</div>
<div class="dish-hint">点击菜品信息 &#x2192; 进入开餐界面</div>
<!-- ============ 常规模式:左右分栏(左大图 + 右信息卡) ============ -->
<div class="normal-mode">
<!-- 顶部副标题 -->
<div class="normal-heading">
<span class="normal-heading__text">先识别 后取餐</span>
</div>
<!-- 中部内容(点击进入开餐界面) -->
<div class="normal-content" id="dishInfo">
<!-- 左侧大图 -->
<div class="normal-img-box" id="dishImg"></div>
<!-- 右侧信息卡 -->
<div class="normal-info">
<div class="normal-info__name" id="dishName">宫保鸡丁</div>
<!-- 价格突出 -->
<div class="normal-info__price">
<span class="normal-info__price-symbol">&#xFFE5;</span>
<span class="normal-info__price-num" id="dishPrice">5</span>
<span class="normal-info__price-unit">元/100克</span>
</div>
<!-- 餐品标签 -->
<div class="normal-tags" id="dishTags"></div>
<!-- 分隔线 -->
<div class="normal-divider"></div>
<!-- 热量 -->
<div class="normal-cal">
<span class="normal-cal__label">热量</span>
<span class="normal-cal__num" id="dishKcal">158.66</span>
<span class="normal-cal__unit">千卡/100克</span>
</div>
</div>
</div>
<!-- 底部进入提示 -->
<div class="normal-hint">点击菜品信息 &#x2192; 进入取餐界面</div>
</div>
<!-- 视频模式布局(纵向:上视频 + 下信息卡,默认隐藏) -->
<!-- ============ 视频模式:上信息条 + 下大视频 ============ -->
<div class="video-mode" id="videoMode">
<!-- 视频播放器 -->
<div class="video-player">
<!-- 视频背景(用 SVG 模拟菜品展示画面) -->
<div class="video-bg" id="videoBg"></div>
<!-- 播放按钮 -->
<div class="video-play-btn" id="videoPlayBtn" title="播放"></div>
<!-- 控制条 -->
<div class="video-controls">
<span style="cursor:pointer;">&#x23EF;</span>
<div class="video-progress"></div>
<span class="video-time">01:23 / 03:45</span>
<span class="video-fullscreen">&#x26F6;</span>
<!-- 顶部信息条 -->
<div class="video-topbar">
<span class="video-topbar__name" id="videoDishName">宫保鸡丁</span>
<!-- 标签(紧跟菜名) -->
<div class="video-topbar__tags" id="videoTags"></div>
<!-- 价格突出(右侧) -->
<div class="video-topbar__price">
<span class="video-topbar__price-symbol">&#xFFE5;</span>
<span class="video-topbar__price-num" id="videoDishPrice">5</span>
<span class="video-topbar__price-unit">元/100克</span>
</div>
</div>
<!-- 餐品信息卡 -->
<div class="video-info-card">
<div class="video-info-name" id="videoDishName">宫保鸡丁</div>
<div class="video-info-divider"></div>
<div class="video-info-item">
<span class="video-info-label">单价</span>
<span class="video-info-value"><span id="videoDishPrice">5</span><span class="video-info-unit">元/100克</span></span>
</div>
<div class="video-info-divider"></div>
<div class="video-info-item">
<span class="video-info-label">热量</span>
<span class="video-info-value"><span id="videoDishKcal">158.66</span><span class="video-info-unit">千卡/100克</span></span>
</div>
</div>
</div>
<!-- 视频模式布局2(横向:左视频 + 右信息卡含标签,默认隐藏 -->
<div class="video-mode-h" id="videoModeH">
<!-- 左侧:视频播放器 -->
<!-- 视频播放器(铺满下方剩余空间 -->
<div class="video-player">
<div class="video-bg" id="videoBgH"></div>
<div class="video-play-btn" id="videoPlayBtnH" title="播放"></div>
<div class="video-bg" id="videoBg"></div>
<div class="video-play-btn" id="videoPlayBtn" title="播放"></div>
<div class="video-controls">
<span style="cursor:pointer;">&#x23EF;</span>
<div class="video-progress"></div>
@@ -564,31 +529,17 @@
<span class="video-fullscreen">&#x26F6;</span>
</div>
</div>
<!-- 右侧:餐品信息卡(含标签) -->
<div class="video-info-card-h">
<!-- 餐品名称 -->
<div class="video-info-name-h" id="videoDishNameH">宫保鸡丁</div>
<!-- 餐品标签 chips -->
<div class="video-tags-row" id="videoTagsRow"></div>
<!-- 分隔线 -->
<div class="video-info-divider-h"></div>
<!-- 单价 -->
<div class="video-info-item-h">
<span class="video-info-label">单价</span>
<span class="video-info-value"><span id="videoDishPriceH">5</span><span class="video-info-unit">元/100克</span></span>
</div>
<!-- 每百克热量 -->
<div class="video-info-item-h">
<span class="video-info-label">每百克热量</span>
<span class="video-info-value"><span id="videoDishKcalH">158.66</span><span class="video-info-unit">千卡/100克</span></span>
</div>
</div>
</div>
</div>
</div>
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
/**
* 待取餐界面交互逻辑
*/
@@ -635,37 +586,57 @@
'</svg>';
}
/* ===== 视频背景 SVG(按菜品色系生成展示画面) ===== */
function videoBgSVG(colors) {
var w = 1200, h = 675; // 16:9 比例,放大以匹配大视频区
var id = 'vidGrad';
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + w + ' ' + h + '" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%;">' +
'<defs><linearGradient id="' + id + '" x1="0" y1="0" x2="1" y2="1">' +
'<stop offset="0%" stop-color="' + colors[0] + '"/>' +
'<stop offset="50%" stop-color="' + colors[1] + '"/>' +
'<stop offset="100%" stop-color="' + colors[2] + '"/></linearGradient></defs>' +
'<rect width="' + w + '" height="' + h + '" fill="url(#' + id + ')"/>' +
'<ellipse cx="' + (w*0.3) + '" cy="' + (h*0.35) + '" rx="280" ry="200" fill="rgba(255,255,255,0.08)"/>' +
'<ellipse cx="' + (w*0.7) + '" cy="' + (h*0.65) + '" rx="340" ry="240" fill="rgba(0,0,0,0.12)"/>' +
'<ellipse cx="' + (w/2) + '" cy="' + (h/2) + '" rx="' + (w*0.32) + '" ry="' + (h*0.35) + '" fill="none" stroke="rgba(255,255,255,0.12)" stroke-width="2"/>' +
'<ellipse cx="' + (w/2) + '" cy="' + (h/2) + '" rx="' + (w*0.22) + '" ry="' + (h*0.22) + '" fill="rgba(255,255,255,0.06)"/>' +
'<ellipse cx="' + (w*0.4) + '" cy="' + (h*0.4) + '" rx="100" ry="70" fill="rgba(255,255,255,0.18)"/>' +
'<ellipse cx="' + (w*0.6) + '" cy="' + (h*0.55) + '" rx="70" ry="45" fill="rgba(0,0,0,0.15)"/>' +
'<text x="' + (w/2) + '" y="' + (h*0.18) + '" text-anchor="middle" fill="rgba(255,255,255,0.6)" font-size="32" font-weight="600" font-family="-apple-system,Microsoft YaHei,sans-serif">餐品制作工艺展示</text>' +
'<text x="' + (w/2) + '" y="' + (h*0.85) + '" text-anchor="middle" fill="rgba(255,255,255,0.35)" font-size="20" font-family="-apple-system,Microsoft YaHei,sans-serif">主厨推荐 · 现场烹制</text>' +
'</svg>';
}
/* ===== 渲染餐品标签(共用:常规模式 + 视频模式) ===== */
function renderTags(containerId, tags) {
var html = '';
for (var i = 0; i < tags.length; i++) {
html += '<span class="dish-tag">' + tags[i] + '</span>';
}
document.getElementById(containerId).innerHTML = html;
}
/* ===== 初始化 ===== */
var dishId = getQueryParam('dishId');
var dishData = (dishId && DISH_MAP[dishId]) || DISH_MAP[2]; // 默认宫保鸡丁
document.getElementById('dishImg').innerHTML = dishFoodSVG(120, 90, dishData.colors);
var dishTags = dishData.tags || [];
/* 常规模式数据填充 */
document.getElementById('dishImg').innerHTML = dishFoodSVG(480, 360, dishData.colors);
document.getElementById('dishName').textContent = dishData.name;
document.getElementById('dishPrice').textContent = dishData.price;
document.getElementById('dishKcal').textContent = dishData.kcal;
renderTags('dishTags', dishTags);
/* ===== 视频模式数据填充(纵向布局) ===== */
/* 视频模式数据填充 */
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);
renderTags('videoTags', dishTags);
/* ===== 视频模式数据填充(横向布局,含标签) ===== */
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 += '<span class="video-tag-chip">' + dishTags[i] + '</span>';
}
tagsRow.innerHTML = tagsHtml;
/* ===== 点击菜品信息 → 进入开餐界面 ===== */
/* ===== 点击菜品信息 → 进入单屏取餐界面 ===== */
document.getElementById('dishInfo').addEventListener('click', function() {
window.location.href = '01-meal-start.html';
window.location.href = '03-meal-pickup.html';
});
/* ===== 演示说明:原 3 秒自动跳转逻辑已移除,改为用户主动点击菜品信息后跳转 ===== */
@@ -693,7 +664,7 @@
window.location.href = '04-settings.html';
});
/* ===== 演示模式切换(常规 / 视频 / 视频2 ===== */
/* ===== 演示模式切换(常规 / 视频) ===== */
var modeSwitch = document.getElementById('modeSwitch');
var mainArea = document.querySelector('.main-area');
modeSwitch.addEventListener('click', function(e) {
@@ -705,46 +676,16 @@
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');
}
// 通过 main-area 的 class 控制布局切换
mainArea.classList.toggle('mode-video', mode === 'video');
});
/* ===== 视频播放按钮(演示用,点击切换播放/暂停图标) ===== */
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 '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + w + ' ' + h + '" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%;">' +
'<defs><linearGradient id="' + id + '" x1="0" y1="0" x2="1" y2="1">' +
'<stop offset="0%" stop-color="' + colors[0] + '"/>' +
'<stop offset="50%" stop-color="' + colors[1] + '"/>' +
'<stop offset="100%" stop-color="' + colors[2] + '"/></linearGradient></defs>' +
'<rect width="' + w + '" height="' + h + '" fill="url(#' + id + ')"/>' +
'<ellipse cx="' + (w*0.3) + '" cy="' + (h*0.35) + '" rx="180" ry="120" fill="rgba(255,255,255,0.08)"/>' +
'<ellipse cx="' + (w*0.7) + '" cy="' + (h*0.65) + '" rx="220" ry="140" fill="rgba(0,0,0,0.12)"/>' +
'<ellipse cx="' + (w/2) + '" cy="' + (h/2) + '" rx="' + (w*0.32) + '" ry="' + (h*0.35) + '" fill="none" stroke="rgba(255,255,255,0.12)" stroke-width="1.5"/>' +
'<ellipse cx="' + (w/2) + '" cy="' + (h/2) + '" rx="' + (w*0.22) + '" ry="' + (h*0.22) + '" fill="rgba(255,255,255,0.06)"/>' +
'<ellipse cx="' + (w*0.4) + '" cy="' + (h*0.4) + '" rx="60" ry="40" fill="rgba(255,255,255,0.18)"/>' +
'<ellipse cx="' + (w*0.6) + '" cy="' + (h*0.55) + '" rx="40" ry="25" fill="rgba(0,0,0,0.15)"/>' +
'<text x="' + (w/2) + '" y="' + (h*0.18) + '" text-anchor="middle" fill="rgba(255,255,255,0.6)" font-size="20" font-weight="600" font-family="-apple-system,Microsoft YaHei,sans-serif">餐品制作工艺展示</text>' +
'<text x="' + (w/2) + '" y="' + (h*0.85) + '" text-anchor="middle" fill="rgba(255,255,255,0.35)" font-size="12" font-family="-apple-system,Microsoft YaHei,sans-serif">主厨推荐 · 现场烹制</text>' +
'</svg>';
}
document.getElementById('videoPlayBtn').addEventListener('click', function() {
videoPlaying = !videoPlaying;
this.style.opacity = videoPlaying ? '0' : '1';
});
</script>
</body>
@@ -1,313 +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; }
/* 外层视口:全屏深色背景,承载居中 PAD 外壳 */
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: linear-gradient(135deg, #0a1628 0%, #0d1f40 50%, #080f1e 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
.main-area {
height: 100%;
display: flex;
flex-direction: column;
padding: 12px 14px;
gap: 12px;
}
.settings-btn {
position: absolute;
top: 8px;
right: 8px;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255,255,255,0.06);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 6px;
font-size: 12px;
color: rgba(255,255,255,0.5);
cursor: pointer;
text-decoration: none;
transition: all 0.2s;
z-index: 10;
}
.settings-btn:hover {
background: rgba(255,255,255,0.1);
color: #fff;
}
.info-row {
display: flex;
align-items: center;
gap: 12px;
flex-shrink: 0;
}
.info-card {
flex: 1;
background: #1a2b4a;
border-radius: 10px;
padding: 12px 16px;
display: flex;
align-items: center;
gap: 12px;
position: relative;
}
.info-card__avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(135deg, #4a90d9, #3570ad);
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.info-card__body { flex: 1; min-width: 0; }
.info-card__name { font-size: 14px; font-weight: 600; margin-bottom: 2px; }
.info-card__id { font-size: 10px; color: rgba(255,255,255,0.4); margin-bottom: 4px; }
.info-card__heat { display: flex; align-items: baseline; gap: 4px; }
.info-card__heat-label { font-size: 11px; color: rgba(255,255,255,0.45); }
.info-card__heat-value { font-size: 18px; font-weight: 700; color: #0AC4A8; line-height: 1; }
.info-card__heat-unit { font-size: 12px; color: rgba(10,196,168,0.6); font-weight: 400; }
.content-row {
display: flex;
flex: 1;
gap: 12px;
min-height: 0;
}
.dish-display {
flex: 1;
background: #1a2b4a;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
min-width: 0;
}
.dish-info {
display: flex;
align-items: center;
justify-content: center;
gap: 18px;
}
.dish-img-box {
width: 120px;
height: 90px;
border-radius: 10px;
overflow: hidden;
flex-shrink: 0;
box-shadow: 0 4px 16px rgba(0,0,0,0.5);
}
.dish-img-box svg { width: 100%; height: 100%; }
.dish-info-text { display: flex; flex-direction: column; gap: 8px; }
.dish-name-row { font-size: 32px; font-weight: 600; }
.dish-name-row .price-info { font-size: 22px; font-weight: 400; color: rgba(255,255,255,0.7); }
.dish-name-row .price-num { color: #0AC4A8; font-weight: 600; }
.dish-cal-row { font-size: 22px; color: rgba(255,255,255,0.6); }
.dish-cal-row .cal-num { color: #0AC4A8; font-weight: 600; }
.pickup-section {
width: 320px;
background: #1a2b4a;
border-radius: 10px;
display: flex;
flex-direction: column;
overflow: hidden;
flex-shrink: 0;
}
.pickup-section__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px 8px;
flex-shrink: 0;
}
.pickup-section__header .section-label {
font-size: 12px;
color: rgba(255,255,255,0.45);
letter-spacing: 0.5px;
}
.pickup-table {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 0 16px;
}
.pickup-header {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 8px 0;
font-size: 11px;
color: rgba(255,255,255,0.4);
border-bottom: 1px solid rgba(255,255,255,0.08);
flex-shrink: 0;
}
.pickup-list {
flex: 1;
overflow-y: auto;
padding: 0;
}
.pickup-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 10px 0;
font-size: 12px;
color: rgba(255,255,255,0.7);
border-bottom: 1px solid rgba(255,255,255,0.04);
}
.pickup-footer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 10px 0;
font-size: 13px;
font-weight: 600;
border-top: 1px solid rgba(255,255,255,0.12);
flex-shrink: 0;
}
.pickup-footer .lbl { color: rgba(255,255,255,0.55); }
.pickup-footer .val { color: #fff; }
.pickup-footer .price-val { color: #0AC4A8; }
.toast {
position: fixed;
top: 40px;
left: 50%;
transform: translateX(-50%) translateY(-20px);
background: rgba(0, 0, 0, 0.85);
color: #fff;
padding: 10px 24px;
border-radius: 8px;
font-size: 12px;
font-weight: 500;
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); }
</style>
</head>
<body>
<div class="device-frame">
<!-- 返回按钮 -->
<div style="position:absolute;top:12px;left:16px;z-index:10;">
<a class="back-btn" id="backBtn" href="javascript:void(0)" style="font-size:14px;color:rgba(255,255,255,0.7);text-decoration:none;cursor:pointer;">&#x25C0; 返回</a>
</div>
<div class="toast" id="toast"></div>
<div class="main-area">
<!-- 用户信息 -->
<div class="info-row">
<div class="info-card">
<div class="info-card__avatar">&#x1F464;</div>
<div class="info-card__body">
<div class="info-card__name">&#x5F20;&#x4E09;</div>
<div class="info-card__id">ID: 98369</div>
<div class="info-card__heat">
<span class="info-card__heat-label">&#x63A8;&#x8350;&#x70ED;&#x91CF;</span>
<span class="info-card__heat-value">720</span>
<span class="info-card__heat-unit">&#x5343;&#x5361;</span>
</div>
</div>
<a class="settings-btn" id="settingsBtn" title="设置">&#x2699;</a>
</div>
</div>
<!-- 左侧餐品展示 + 右侧取餐记录 -->
<div class="content-row">
<div class="dish-display">
<div class="dish-info">
<div class="dish-img-box" id="dishImg"></div>
<div class="dish-info-text">
<div class="dish-name-row">
&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;
<span class="price-info">(单价 <span class="price-num">5</span> &#x5143;/100&#x514B;</span>
</div>
<div class="dish-cal-row">
热量 <span class="cal-num">158.66</span> &#x5343;&#x5361;/100&#x514B;
</div>
</div>
</div>
</div>
<div class="pickup-section">
<div class="pickup-section__header">
<span class="section-label">&#x1F9FE; &#x53D6;&#x9910;&#x8BB0;&#x5F55;</span>
</div>
<div class="pickup-table">
<div class="pickup-header">
<span>&#x9910;&#x54C1;&#x540D;&#x79F0;</span>
<span>&#x91CD;&#x91CF;(&#x514B;)</span>
<span>&#x5C0F;&#x8BA1;(&#x5143;)</span>
</div>
<div class="pickup-list">
<div class="pickup-row">
<span>&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;</span><span>186</span><span>9.30</span>
</div>
<div class="pickup-row">
<span>&#x5927;&#x7C73;&#x996D;</span><span>200</span><span>3.00</span>
</div>
<div class="pickup-row">
<span>&#x6E05;&#x7092;&#x65F6;&#x852C;</span><span>120</span><span>3.60</span>
</div>
<div class="pickup-row">
<span>&#x7D2B;&#x83DC;&#x86CB;&#x82B1;&#x6C64;</span><span>250</span><span>5.00</span>
</div>
</div>
<div class="pickup-footer">
<span class="lbl">&#x5408;&#x8BA1;</span>
<span class="val">756&#x514B;</span>
<span class="price-val">20.90&#x5143;</span>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.getElementById('settingsBtn').addEventListener('click', function(e) {
e.preventDefault();
window.location.href = '04-settings.html';
});
function dishFoodSVG(w, h, colors) {
var id = 'dg';
return '<svg xmlns="http://www.w3.org/2000/svg" width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '">' +
'<defs><linearGradient id="' + id + '" x1="0" y1="0" x2="1" y2="1">' +
'<stop offset="0%" stop-color="' + colors[0] + '"/>' +
'<stop offset="50%" stop-color="' + colors[1] + '"/>' +
'<stop offset="100%" stop-color="' + colors[2] + '"/></linearGradient></defs>' +
'<rect width="' + w + '" height="' + h + '" fill="url(#' + id + ')"/>' +
'<ellipse cx="' + (w*0.4) + '" cy="' + (h*0.45) + '" rx="' + (w*0.3) + '" ry="' + (h*0.25) + '" fill="rgba(255,255,255,0.08)"/>' +
'<ellipse cx="' + (w*0.6) + '" cy="' + (h*0.55) + '" rx="' + (w*0.25) + '" ry="' + (h*0.2) + '" fill="rgba(0,0,0,0.1)"/>' +
'<ellipse cx="' + (w*0.35) + '" cy="' + (h*0.35) + '" rx="' + (w*0.12) + '" ry="' + (h*0.1) + '" fill="rgba(255,255,255,0.15)"/>' +
'</svg>';
}
document.getElementById('dishImg').innerHTML = dishFoodSVG(120, 90, ['#C87030', '#E8A040', '#D08028']);
</script>
</body>
</html>
@@ -1,182 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=480, 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: 480px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.screen-frame {
width: 480px;
height: 320px;
background: linear-gradient(180deg, #1a2b4a 0%, #142038 100%);
border-radius: 16px;
display: flex;
flex-direction: column;
overflow: hidden;
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(74, 144, 217, 0.15);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 16px;
border-bottom: 1px solid rgba(255,255,255,0.06);
flex-shrink: 0;
}
.header .n-title {
font-size: 9px;
font-weight: 600;
color: #fff;
}
.header .n-meal {
font-size: 8px;
color: rgba(255,255,255,0.45);
}
.header .n-time {
font-size: 7px;
color: rgba(255,255,255,0.3);
margin-left: 6px;
}
.cyl-group {
flex: 1;
display: flex;
align-items: flex-end;
justify-content: center;
gap: 28px;
padding: 10px 16px 8px;
}
.cyl-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.cyl-value {
font-size: 10px;
font-weight: 700;
color: #fff;
text-align: center;
line-height: 1.3;
}
.cyl-value .cyl-unit {
font-size: 7px;
font-weight: 400;
opacity: 0.7;
}
.cyl-svg { display: block; }
.cyl-label {
font-size: 8px;
color: rgba(255,255,255,0.6);
text-align: center;
}
</style>
</head>
<body>
<div class="screen-frame">
<!-- 返回按钮 -->
<div style="position:absolute;top:12px;left:16px;z-index:10;">
<a class="back-btn" id="backBtn" href="javascript:void(0)" style="font-size:14px;color:rgba(255,255,255,0.7);text-decoration:none;cursor:pointer;">&#x25C0; 返回</a>
</div>
<div class="header">
<span class="n-title">&#x1F4CA; &#x672C;&#x9910;&#x6B21;&#x6444;&#x5165;</span>
<span>
<span class="n-meal">&#x5F53;&#x524D;&#x9910;&#x6B21;&#xFF1A;&#x65E9;&#x9910;</span>
<span class="n-time">06:00 ~ 10:19</span>
</span>
</div>
<div class="cyl-group">
<!-- 热量柱 -->
<div class="cyl-item">
<div class="cyl-value">1070<span class="cyl-unit">千卡</span></div>
<svg class="cyl-svg" width="72" height="190" viewBox="0 0 72 190">
<defs>
<linearGradient id="heatGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#cc1111"/>
<stop offset="50%" stop-color="#ff2020"/>
<stop offset="100%" stop-color="#cc1111"/>
</linearGradient>
</defs>
<ellipse cx="36" cy="8" rx="32" ry="7" fill="#cc1111"/>
<rect x="4" y="8" width="64" height="175" fill="url(#heatGrad)"/>
<rect x="8" y="8" width="8" height="175" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="36" cy="8" rx="30" ry="6" fill="rgba(255,255,255,0.15)"/>
<text x="36" y="178" text-anchor="middle" font-size="14">&#x1F525;</text>
</svg>
<div class="cyl-label">热量</div>
</div>
<!-- 主食柱 -->
<div class="cyl-item">
<div class="cyl-value">68<span class="cyl-unit"></span></div>
<svg class="cyl-svg" width="56" height="120" viewBox="0 0 56 120">
<defs>
<linearGradient id="stapleGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#68a868"/>
<stop offset="50%" stop-color="#88cc88"/>
<stop offset="100%" stop-color="#68a868"/>
</linearGradient>
</defs>
<ellipse cx="28" cy="8" rx="26" ry="6" fill="#68a868"/>
<rect x="2" y="8" width="52" height="105" fill="url(#stapleGrad)"/>
<rect x="6" y="8" width="6" height="105" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="28" cy="8" rx="24" ry="5" fill="rgba(255,255,255,0.15)"/>
<text x="28" y="108" text-anchor="middle" font-size="12">&#x1F35A;</text>
</svg>
<div class="cyl-label">主食</div>
</div>
<!-- 果蔬柱 -->
<div class="cyl-item">
<div class="cyl-value">68<span class="cyl-unit"></span></div>
<svg class="cyl-svg" width="56" height="120" viewBox="0 0 56 120">
<defs>
<linearGradient id="vegGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#68a868"/>
<stop offset="50%" stop-color="#88cc88"/>
<stop offset="100%" stop-color="#68a868"/>
</linearGradient>
</defs>
<ellipse cx="28" cy="8" rx="26" ry="6" fill="#68a868"/>
<rect x="2" y="8" width="52" height="105" fill="url(#vegGrad)"/>
<rect x="6" y="8" width="6" height="105" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="28" cy="8" rx="24" ry="5" fill="rgba(255,255,255,0.15)"/>
<text x="28" y="108" text-anchor="middle" font-size="12">&#x1F957;</text>
</svg>
<div class="cyl-label">果蔬</div>
</div>
<!-- 肉蛋柱 -->
<div class="cyl-item">
<div class="cyl-value">68<span class="cyl-unit"></span></div>
<svg class="cyl-svg" width="56" height="105" viewBox="0 0 56 105">
<defs>
<linearGradient id="meatGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#cc1111"/>
<stop offset="50%" stop-color="#ff2020"/>
<stop offset="100%" stop-color="#cc1111"/>
</linearGradient>
</defs>
<ellipse cx="28" cy="8" rx="26" ry="6" fill="#cc1111"/>
<rect x="2" y="8" width="52" height="90" fill="url(#meatGrad)"/>
<rect x="6" y="8" width="6" height="90" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="28" cy="8" rx="24" ry="5" fill="rgba(255,255,255,0.15)"/>
<text x="28" y="94" text-anchor="middle" font-size="12">&#x1F969;</text>
</svg>
<div class="cyl-label">肉蛋</div>
</div>
</div>
</div>
<script>
</script>
</body>
</html>
@@ -0,0 +1,761 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1920, 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: 1820px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
/* 双屏容器:左侧大屏 + 右侧小屏横向排列 */
.dual-wrap {
display: flex;
align-items: center;
gap: 24px;
position: relative;
}
.screen-label {
position: absolute;
top: -28px;
left: 0;
font-size: 12px;
color: rgba(255,255,255,0.4);
letter-spacing: 1px;
}
.dual-col { position: relative; }
.dual-col--large .screen-label { left: 0; }
.dual-col--small .screen-label { left: 0; }
/* ===== 左侧:大屏 PAD 外壳 1280×720 ===== */
.device-frame {
width: 1280px;
height: 720px;
background: linear-gradient(135deg, #0a1628 0%, #0d1f40 50%, #080f1e 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* ===== 主内容区:两列网格(参考 03-meal-pickup) ===== */
.large-main {
height: 100%;
display: grid;
grid-template-columns: 1fr 320px;
padding: 16px 20px;
gap: 16px;
}
/* 中列:用户信息 + 餐品介绍 纵向堆叠 */
.center-column {
display: flex;
flex-direction: column;
gap: 12px;
min-width: 0;
}
/* 设置按钮(浮于 pickup-section 头部) */
.settings-btn {
width: 32px; height: 32px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255,255,255,0.06);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 6px;
font-size: 16px;
color: rgba(255,255,255,0.6);
cursor: pointer;
text-decoration: none;
transition: all 0.2s;
flex-shrink: 0;
}
.settings-btn:hover { background: rgba(255,255,255,0.1); color: #fff; }
/* ===== 用户信息 + 餐品信息 横排 ===== */
.info-row {
display: flex;
gap: 12px;
flex-shrink: 0;
}
.info-card {
flex: 1;
background: #1a2b4a;
border-radius: 10px;
padding: 12px 16px;
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
}
.info-card__avatar {
width: 42px; height: 42px;
border-radius: 50%;
background: linear-gradient(135deg, #4a90d9, #3570ad);
display: flex; align-items: center; justify-content: center;
font-size: 20px; flex-shrink: 0;
}
.info-card__body { flex: 1; min-width: 0; }
/* 用户信息卡:第一行 姓名 + 编号 同行 */
.info-card__line {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 4px;
white-space: nowrap;
}
.info-card__name {
font-size: 22px;
font-weight: 700;
line-height: 1.1;
color: #fff;
}
.info-card__id {
font-size: 16px;
color: rgba(255,255,255,0.55);
font-weight: 500;
}
/* 第二行:推荐热量 + 范围值 */
.info-card__heat {
display: flex;
align-items: baseline;
gap: 6px;
white-space: nowrap;
}
.info-card__label {
font-size: 11px;
color: rgba(255,255,255,0.45);
font-weight: 400;
}
.info-card__value {
font-size: 16px;
font-weight: 700;
color: #0AC4A8;
line-height: 1.1;
}
.info-card__unit {
font-size: 11px;
font-weight: 400;
color: rgba(10,196,168,0.7);
}
/* ===== 餐品信息卡 ===== */
.info-card--dish {
cursor: pointer;
transition: background 0.2s;
}
.info-card--dish:hover {
background: rgba(74,144,217,0.12);
}
.info-card__dish-line {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-bottom: 4px;
}
.info-card__dish-name {
font-size: 15px;
font-weight: 600;
line-height: 1.1;
white-space: nowrap;
color: #fff;
}
.info-card__dish-price {
font-size: 36px;
font-weight: 800;
color: #FFB236;
line-height: 1;
letter-spacing: -0.5px;
white-space: nowrap;
text-shadow: 0 1px 6px rgba(255,140,40,0.45);
}
.info-card__dish-price .price-unit {
font-size: 15px;
font-weight: 600;
color: rgba(255,178,54,0.85);
margin-left: 3px;
letter-spacing: 0;
text-shadow: none;
}
.info-card__dish-heat {
font-size: 11px;
color: rgba(255,255,255,0.5);
line-height: 1.3;
}
.info-card__dish-heat em {
font-style: normal;
color: #0AC4A8;
font-weight: 600;
}
/* ===== 当前餐次标题行(参考单屏 03 nutrition-header-row) ===== */
.meal-header-row {
display: flex;
align-items: center;
justify-content: space-between;
background: #1a2b4a;
border-radius: 10px;
padding: 12px 20px;
flex-shrink: 0;
}
.meal-header-row .n-title {
font-size: 16px;
font-weight: 600;
color: #fff;
}
.meal-header-row .n-title-hint {
font-size: 12px;
font-weight: 400;
color: #FFB236;
margin-left: 4px;
}
.meal-header-row .n-meal {
font-size: 13px;
color: rgba(255,255,255,0.5);
}
.meal-header-row .n-time {
font-size: 12px;
color: rgba(255,255,255,0.35);
margin-left: 12px;
}
/* ===== 中列下半部:餐品介绍(替代 nutrition-core) ===== */
.dish-display {
flex: 1;
background: linear-gradient(180deg, #1a2b4a 0%, #142038 100%);
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
min-height: 0;
}
.dish-info {
display: flex;
align-items: center;
justify-content: center;
gap: 32px;
width: 100%;
}
.dish-img-box {
width: 320px; height: 320px;
border-radius: 20px;
overflow: hidden;
flex-shrink: 0;
box-shadow: 0 12px 32px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.06);
}
.dish-img-box svg { width: 100%; height: 100%; }
.dish-info-text {
display: flex;
flex-direction: column;
gap: 16px;
flex: 1;
min-width: 0;
max-width: 420px;
}
.dish-name-row {
font-size: 38px;
font-weight: 700;
color: #fff;
line-height: 1.2;
}
/* 价格胶囊(青色) */
.dish-price-pill {
display: flex;
align-items: baseline;
gap: 6px;
padding: 10px 20px;
background: linear-gradient(135deg, rgba(10,196,168,0.18), rgba(10,196,168,0.06));
border: 1px solid rgba(10,196,168,0.4);
border-radius: 12px;
width: fit-content;
}
.dish-price-pill__symbol {
font-size: 20px;
font-weight: 600;
color: #0AC4A8;
}
.dish-price-pill__num {
font-size: 44px;
font-weight: 800;
color: #0AC4A8;
line-height: 1;
text-shadow: 0 0 16px rgba(10,196,168,0.35);
}
.dish-price-pill__unit {
font-size: 14px;
color: rgba(10,196,168,0.8);
font-weight: 400;
}
/* 餐品标签 chips */
.dish-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.dish-tag {
display: inline-flex;
align-items: center;
padding: 5px 12px;
font-size: 13px;
color: #0AC4A8;
background: rgba(10,196,168,0.12);
border: 1px solid rgba(10,196,168,0.25);
border-radius: 12px;
letter-spacing: 0.5px;
white-space: nowrap;
}
.dish-tag:nth-child(3n+2) {
color: #FF9800;
background: rgba(255,152,0,0.10);
border-color: rgba(255,152,0,0.25);
}
.dish-tag:nth-child(3n) {
color: #5B9BF8;
background: rgba(91,155,248,0.12);
border-color: rgba(91,155,248,0.25);
}
.dish-divider {
width: 100%;
height: 1px;
background: rgba(255,255,255,0.1);
}
.dish-cal-row {
display: flex;
align-items: baseline;
gap: 8px;
}
.dish-cal-row__label {
font-size: 13px;
color: rgba(255,255,255,0.5);
letter-spacing: 0.5px;
}
.dish-cal-row__num {
font-size: 26px;
font-weight: 700;
color: #fff;
}
.dish-cal-row__unit {
font-size: 12px;
color: rgba(255,255,255,0.5);
}
/* ===== 右列:取餐记录(通顶) ===== */
.right-column {
display: flex;
flex-direction: column;
min-width: 0;
}
.pickup-section {
flex: 1;
background: #1a2b4a;
border-radius: 10px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.pickup-section__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px 8px;
flex-shrink: 0;
}
.pickup-section__header .section-label {
font-size: 12px;
color: rgba(255,255,255,0.4);
letter-spacing: 0.5px;
}
.pickup-table {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 0 16px;
}
.pickup-header {
display: grid; grid-template-columns: 1fr 1fr 1fr;
padding: 8px 0; font-size: 12px;
color: rgba(255,255,255,0.45);
border-bottom: 1px solid rgba(255,255,255,0.08);
flex-shrink: 0;
}
.pickup-list { flex: 1; overflow-y: auto; padding: 0; }
.pickup-row {
display: grid; grid-template-columns: 1fr 1fr 1fr;
padding: 10px 0; font-size: 13px;
color: rgba(255,255,255,0.7);
border-bottom: 1px solid rgba(255,255,255,0.04);
}
/* 合计区:橙色胶囊(沿用单屏 03 样式) */
.pickup-footer {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
margin-top: 6px;
padding: 14px 14px;
background: linear-gradient(135deg, rgba(255,178,54,0.2) 0%, rgba(255,140,40,0.32) 100%);
border: 1px solid rgba(255,178,54,0.5);
border-radius: 8px;
box-shadow: 0 4px 14px rgba(255,140,40,0.25);
flex-shrink: 0;
}
.pickup-footer .lbl {
color: rgba(255,255,255,0.85);
font-size: 14px;
font-weight: 700;
letter-spacing: 1px;
white-space: nowrap;
}
.pickup-footer .val {
color: #fff;
font-size: 15px;
font-weight: 700;
white-space: nowrap;
}
/* 超大醒目金额:40px,800字重,橙色高亮+发光阴影 */
.pickup-footer .price-val {
color: #FFB236;
font-size: 40px;
font-weight: 800;
text-shadow: 0 2px 10px rgba(255,140,40,0.6);
letter-spacing: -1px;
line-height: 1;
white-space: nowrap;
}
.pickup-footer .price-val::before {
content: '\FFE5';
font-size: 20px;
font-weight: 600;
margin-right: 3px;
vertical-align: 5px;
}
/* ===== 右侧:小屏副屏外壳 480×320 ===== */
.screen-frame {
width: 480px;
height: 320px;
background: linear-gradient(180deg, #1a2b4a 0%, #142038 100%);
border-radius: 16px;
display: flex;
flex-direction: column;
overflow: hidden;
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(74, 144, 217, 0.15);
}
.small-header {
display: flex; align-items: center; justify-content: space-between;
padding: 8px 16px;
border-bottom: 1px solid rgba(255,255,255,0.06);
flex-shrink: 0;
}
.small-header .n-title { font-size: 9px; font-weight: 600; color: #fff; }
/* 标题内推荐热量副文案:字号更小 + 暖橙色区分 */
.small-header .n-title .n-sub {
font-size: 8px;
font-weight: 400;
color: #FFB236;
margin-left: 4px;
letter-spacing: 0.2px;
}
.small-header .n-meal { font-size: 8px; color: rgba(255,255,255,0.45); }
.small-header .n-time { font-size: 7px; color: rgba(255,255,255,0.3); margin-left: 6px; }
.cyl-group {
flex: 1;
display: flex; align-items: flex-end; justify-content: center;
gap: 28px; padding: 10px 16px 8px;
}
.cyl-item { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.cyl-value { font-size: 10px; font-weight: 700; color: #fff; text-align: center; line-height: 1.3; }
.cyl-value .cyl-unit { font-size: 7px; font-weight: 400; opacity: 0.7; }
.cyl-svg { display: block; }
.cyl-label { font-size: 8px; color: rgba(255,255,255,0.6); text-align: center; }
/* ===== 顶部返回按钮(浮于双屏容器之上) ===== */
.back-btn {
position: fixed;
top: 20px;
left: 20px;
z-index: 100;
font-size: 14px;
color: rgba(255,255,255,0.7);
text-decoration: none;
cursor: pointer;
background: rgba(0,0,0,0.4);
padding: 6px 12px;
border-radius: 6px;
}
.back-btn:hover { color: #fff; background: rgba(0,0,0,0.6); }
.toast {
position: fixed;
top: 40px;
left: 50%;
transform: translateX(-50%) translateY(-20px);
background: rgba(0, 0, 0, 0.85);
color: #fff;
padding: 10px 24px;
border-radius: 8px;
font-size: 12px;
font-weight: 500;
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); }
</style>
</head>
<body>
<!-- 返回按钮 -->
<a class="back-btn" id="backBtn" href="javascript:void(0)">&#x25C0; 返回</a>
<div class="toast" id="toast"></div>
<div class="dual-wrap">
<!-- ===== 左:大屏 ===== -->
<div class="dual-col dual-col--large">
<span class="screen-label">大屏 · 1280×720</span>
<div class="device-frame">
<div class="large-main">
<!-- ===== 中列:用户信息 + 餐品信息 + 餐品介绍 ===== -->
<div class="center-column">
<!-- 用户信息 + 餐品信息 横排 -->
<div class="info-row">
<!-- 用户信息卡 -->
<div class="info-card">
<div class="info-card__avatar">&#x1F464;</div>
<div class="info-card__body">
<div class="info-card__line" style="justify-content:space-between;margin-bottom:0;">
<span class="info-card__name">&#x5F20;&#x4E09;</span>
<span class="info-card__id">&#x7F16;&#x53F7;: 98369</span>
</div>
</div>
</div>
<!-- 餐品信息卡 -->
<div class="info-card info-card--dish" id="dishInfoCard">
<div class="info-card__body">
<div class="info-card__dish-line">
<span class="info-card__dish-name">&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;</span>
<span class="info-card__dish-price">5<span class="price-unit">&#x5143;/100g</span></span>
</div>
</div>
</div>
</div>
<!-- 当前餐次标题行 -->
<div class="meal-header-row">
<span class="n-title">&#x1F4CA; &#x672C;&#x9910;&#x6B21;&#x6444;&#x5165;<span class="n-title-hint">&#xFF08;&#x63A8;&#x8350;&#x70ED;&#x91CF; 580~720 &#x5343;&#x5361;&#xFF09;</span></span>
<span>
<span class="n-meal">&#x5F53;&#x524D;&#x9910;&#x6B21;&#xFF1A;&#x65E9;&#x9910;</span>
<span class="n-time">06:00 ~ 10:19</span>
</span>
</div>
<!-- 餐品介绍(替代原 nutrition-core) -->
<div class="dish-display">
<div class="dish-info">
<div class="dish-img-box" id="dishImg"></div>
<div class="dish-info-text">
<div class="dish-name-row">&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;</div>
<div class="dish-price-pill">
<span class="dish-price-pill__symbol">&#xFFE5;</span>
<span class="dish-price-pill__num">5</span>
<span class="dish-price-pill__unit">&#x5143;/100&#x514B;</span>
</div>
<div class="dish-tags">
<span class="dish-tag">&#x9AD8;&#x86CB;&#x767D;</span>
<span class="dish-tag">&#x4F4E;&#x82A5;&#x9178;</span>
<span class="dish-tag">&#x8425;&#x517B;&#x5747;&#x8861;</span>
</div>
<div class="dish-divider"></div>
<div class="dish-cal-row">
<span class="dish-cal-row__label">&#x70ED;&#x91CF;</span>
<span class="dish-cal-row__num">158.66</span>
<span class="dish-cal-row__unit">&#x5343;&#x5361;/100&#x514B;</span>
</div>
</div>
</div>
</div>
</div>
<!-- ===== 右列:取餐记录(通顶) ===== -->
<div class="right-column">
<div class="pickup-section">
<div class="pickup-section__header">
<span class="section-label">&#x1F9FE; &#x53D6;&#x9910;&#x8BB0;&#x5F55;</span>
<a class="settings-btn" id="settingsBtn" title="设置">&#x2699;</a>
</div>
<div class="pickup-table">
<div class="pickup-header">
<span>&#x9910;&#x54C1;&#x540D;&#x79F0;</span>
<span>&#x91CD;&#x91CF;(&#x514B;)</span>
<span>&#x5C0F;&#x8BA1;(&#x5143;)</span>
</div>
<div class="pickup-list">
<div class="pickup-row">
<span>&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;</span><span>186</span><span>9.30</span>
</div>
<div class="pickup-row">
<span>&#x5927;&#x7C73;&#x996D;</span><span>200</span><span>3.00</span>
</div>
<div class="pickup-row">
<span>&#x6E05;&#x7092;&#x65F6;&#x852C;</span><span>120</span><span>3.60</span>
</div>
<div class="pickup-row">
<span>&#x7D2B;&#x83DC;&#x86CB;&#x82B1;&#x6C64;</span><span>250</span><span>5.00</span>
</div>
</div>
<div class="pickup-footer">
<span class="lbl">&#x5408;&#x8BA1;</span>
<span class="val">756&#x514B;</span>
<span class="price-val">20.90</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ===== 右:小屏 ===== -->
<div class="dual-col dual-col--small">
<span class="screen-label">小屏 · 480×320</span>
<div class="screen-frame">
<div class="small-header">
<span class="n-title">&#x1F4CA; &#x672C;&#x9910;&#x6B21;&#x6444;&#x5165;<span class="n-sub">&#x63A8;&#x8350;&#x70ED;&#x91CF; 580~720 &#x5343;&#x5361;</span></span>
<span>
<span class="n-meal">&#x5F53;&#x524D;&#x9910;&#x6B21;&#xFF1A;&#x65E9;&#x9910;</span>
<span class="n-time">06:00 ~ 10:19</span>
</span>
</div>
<div class="cyl-group">
<!-- 热量柱 -->
<div class="cyl-item">
<div class="cyl-value">1070<span class="cyl-unit">千卡</span></div>
<svg class="cyl-svg" width="72" height="190" viewBox="0 0 72 190">
<defs>
<linearGradient id="heatGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#cc1111"/>
<stop offset="50%" stop-color="#ff2020"/>
<stop offset="100%" stop-color="#cc1111"/>
</linearGradient>
</defs>
<ellipse cx="36" cy="8" rx="32" ry="7" fill="#cc1111"/>
<rect x="4" y="8" width="64" height="175" fill="url(#heatGrad)"/>
<rect x="8" y="8" width="8" height="175" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="36" cy="8" rx="30" ry="6" fill="rgba(255,255,255,0.15)"/>
<text x="36" y="178" text-anchor="middle" font-size="14">&#x1F525;</text>
</svg>
<div class="cyl-label">热量</div>
</div>
<!-- 主食柱 -->
<div class="cyl-item">
<div class="cyl-value">68<span class="cyl-unit"></span></div>
<svg class="cyl-svg" width="56" height="120" viewBox="0 0 56 120">
<defs>
<linearGradient id="stapleGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#68a868"/>
<stop offset="50%" stop-color="#88cc88"/>
<stop offset="100%" stop-color="#68a868"/>
</linearGradient>
</defs>
<ellipse cx="28" cy="8" rx="26" ry="6" fill="#68a868"/>
<rect x="2" y="8" width="52" height="105" fill="url(#stapleGrad)"/>
<rect x="6" y="8" width="6" height="105" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="28" cy="8" rx="24" ry="5" fill="rgba(255,255,255,0.15)"/>
<text x="28" y="108" text-anchor="middle" font-size="12">&#x1F35A;</text>
</svg>
<div class="cyl-label">主食</div>
</div>
<!-- 果蔬柱 -->
<div class="cyl-item">
<div class="cyl-value">68<span class="cyl-unit"></span></div>
<svg class="cyl-svg" width="56" height="120" viewBox="0 0 56 120">
<defs>
<linearGradient id="vegGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#68a868"/>
<stop offset="50%" stop-color="#88cc88"/>
<stop offset="100%" stop-color="#68a868"/>
</linearGradient>
</defs>
<ellipse cx="28" cy="8" rx="26" ry="6" fill="#68a868"/>
<rect x="2" y="8" width="52" height="105" fill="url(#vegGrad)"/>
<rect x="6" y="8" width="6" height="105" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="28" cy="8" rx="24" ry="5" fill="rgba(255,255,255,0.15)"/>
<text x="28" y="108" text-anchor="middle" font-size="12">&#x1F957;</text>
</svg>
<div class="cyl-label">果蔬</div>
</div>
<!-- 肉蛋柱 -->
<div class="cyl-item">
<div class="cyl-value">68<span class="cyl-unit"></span></div>
<svg class="cyl-svg" width="56" height="105" viewBox="0 0 56 105">
<defs>
<linearGradient id="meatGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#cc1111"/>
<stop offset="50%" stop-color="#ff2020"/>
<stop offset="100%" stop-color="#cc1111"/>
</linearGradient>
</defs>
<ellipse cx="28" cy="8" rx="26" ry="6" fill="#cc1111"/>
<rect x="2" y="8" width="52" height="90" fill="url(#meatGrad)"/>
<rect x="6" y="8" width="6" height="90" fill="rgba(255,255,255,0.08)"/>
<ellipse cx="28" cy="8" rx="24" ry="5" fill="rgba(255,255,255,0.15)"/>
<text x="28" y="94" text-anchor="middle" font-size="12">&#x1F969;</text>
</svg>
<div class="cyl-label">肉蛋</div>
</div>
</div>
</div>
</div>
</div>
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
/* ===== 设置按钮 ===== */
document.getElementById('settingsBtn').addEventListener('click', function(e) {
e.preventDefault();
window.location.href = '04-settings.html';
});
/* ===== 点击餐品信息卡 → 进入开餐界面 ===== */
document.getElementById('dishInfoCard').addEventListener('click', function() {
window.location.href = '01-meal-start.html';
});
/* ===== 餐品占位图(SVG) ===== */
function dishFoodSVG(w, h, colors) {
var id = 'dg';
return '<svg xmlns="http://www.w3.org/2000/svg" width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '">' +
'<defs><linearGradient id="' + id + '" x1="0" y1="0" x2="1" y2="1">' +
'<stop offset="0%" stop-color="' + colors[0] + '"/>' +
'<stop offset="50%" stop-color="' + colors[1] + '"/>' +
'<stop offset="100%" stop-color="' + colors[2] + '"/></linearGradient></defs>' +
'<rect width="' + w + '" height="' + h + '" fill="url(#' + id + ')"/>' +
'<ellipse cx="' + (w*0.4) + '" cy="' + (h*0.45) + '" rx="' + (w*0.3) + '" ry="' + (h*0.25) + '" fill="rgba(255,255,255,0.08)"/>' +
'<ellipse cx="' + (w*0.6) + '" cy="' + (h*0.55) + '" rx="' + (w*0.25) + '" ry="' + (h*0.2) + '" fill="rgba(0,0,0,0.1)"/>' +
'<ellipse cx="' + (w*0.35) + '" cy="' + (h*0.35) + '" rx="' + (w*0.12) + '" ry="' + (h*0.1) + '" fill="rgba(255,255,255,0.15)"/>' +
'</svg>';
}
document.getElementById('dishImg').innerHTML = dishFoodSVG(320, 320, ['#C87030', '#E8A040', '#D08028']);
</script>
</body>
</html>
@@ -74,24 +74,44 @@
flex-shrink: 0;
}
.info-card__body { flex: 1; min-width: 0; }
.info-card__name { font-size: 15px; font-weight: 600; }
.info-card__id { font-size: 11px; color: rgba(255,255,255,0.4); }
.info-card__right { text-align: right; flex-shrink: 0; }
.info-card__label { font-size: 10px; color: rgba(255,255,255,0.4); }
.info-card__value { font-size: 17px; font-weight: 700; color: #0AC4A8; }
.info-card__unit { font-size: 10px; font-weight: 400; color: rgba(10,196,168,0.6); }
/* 第一行:姓名 + ID 同行,强制不换行 */
.info-card__line {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 4px;
white-space: nowrap;
}
.info-card__name { font-size: 22px; font-weight: 700; line-height: 1.1; }
.info-card__id {
font-size: 16px;
color: rgba(255,255,255,0.55);
font-weight: 500;
}
/* 第二行:推荐热量 + 范围值,强制不换行 */
.info-card__heat {
display: flex;
align-items: baseline;
gap: 6px;
white-space: nowrap;
}
.info-card__label {
font-size: 11px;
color: rgba(255,255,255,0.45);
font-weight: 400;
}
.info-card__value {
font-size: 16px;
font-weight: 700;
color: #0AC4A8;
line-height: 1.1;
}
.info-card__unit {
font-size: 11px;
font-weight: 400;
color: rgba(10,196,168,0.7);
}
.info-card__emoji {
width: 48px;
height: 48px;
border-radius: 8px;
overflow: hidden;
flex-shrink: 0;
}
.info-card__emoji svg {
width: 100%;
height: 100%;
}
.info-card--dish {
cursor: pointer;
transition: background 0.2s;
@@ -99,9 +119,48 @@
.info-card--dish:hover {
background: rgba(74,144,217,0.12);
}
.info-card__dish-name { font-size: 14px; font-weight: 600; margin-bottom: 2px; }
.info-card__dish-detail { font-size: 11px; color: rgba(255,255,255,0.45); line-height: 1.4; }
.info-card__dish-detail em { font-style: normal; color: #0AC4A8; font-weight: 600; }
/* 菜品行:名称 + 价格(靠右) */
.info-card__dish-line {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-bottom: 4px;
}
.info-card__dish-name {
font-size: 15px;
font-weight: 600;
line-height: 1.1;
white-space: nowrap;
}
/* 醒目价格:放大到 36px,带元/100g 单位 */
.info-card__dish-price {
font-size: 36px;
font-weight: 800;
color: #FFB236;
line-height: 1;
letter-spacing: -0.5px;
white-space: nowrap;
text-shadow: 0 1px 6px rgba(255,140,40,0.45);
}
.info-card__dish-price .price-unit {
font-size: 15px;
font-weight: 600;
color: rgba(255,178,54,0.85);
margin-left: 3px;
letter-spacing: 0;
text-shadow: none;
}
.info-card__dish-heat {
font-size: 11px;
color: rgba(255,255,255,0.5);
line-height: 1.3;
}
.info-card__dish-heat em {
font-style: normal;
color: #0AC4A8;
font-weight: 600;
}
/* 营养标题行 */
.nutrition-header-row {
@@ -118,6 +177,13 @@
font-weight: 600;
color: #fff;
}
/* 标题行内的推荐热量提示:小字号+淡青色,作为辅助信息弱化视觉权重 */
.nutrition-header-row .n-title-hint {
font-size: 12px;
font-weight: 400;
color: #0AC4A8;
margin-left: 4px;
}
.nutrition-header-row .n-meal {
font-size: 13px;
color: rgba(255,255,255,0.5);
@@ -262,18 +328,50 @@
color: rgba(255,255,255,0.7);
border-bottom: 1px solid rgba(255,255,255,0.04);
}
/* 合计区:单行排布,合计/重量/金额一行,金额最大化 */
.pickup-footer {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 10px 0;
font-size: 13px;
font-weight: 600;
border-top: 1px solid rgba(255,255,255,0.12);
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
margin-top: 6px;
padding: 14px 14px;
background: linear-gradient(135deg, rgba(255,178,54,0.2) 0%, rgba(255,140,40,0.32) 100%);
border: 1px solid rgba(255,178,54,0.5);
border-radius: 8px;
box-shadow: 0 4px 14px rgba(255,140,40,0.25);
flex-shrink: 0;
}
.pickup-footer .lbl { color: rgba(255,255,255,0.55); }
.pickup-footer .val { color: #fff; }
.pickup-footer .price-val { color: #0AC4A8; }
.pickup-footer .lbl {
color: rgba(255,255,255,0.85);
font-size: 14px;
font-weight: 700;
letter-spacing: 1px;
white-space: nowrap;
}
.pickup-footer .val {
color: #fff;
font-size: 15px;
font-weight: 700;
white-space: nowrap;
}
/* 超大醒目金额:40px,800字重,橙色高亮+发光阴影 */
.pickup-footer .price-val {
color: #FFB236;
font-size: 40px;
font-weight: 800;
text-shadow: 0 2px 10px rgba(255,140,40,0.6);
letter-spacing: -1px;
line-height: 1;
white-space: nowrap;
}
.pickup-footer .price-val::before {
content: '\FFE5';
font-size: 20px;
font-weight: 600;
margin-right: 3px;
vertical-align: 5px;
}
/* Toast */
.toast {
@@ -324,26 +422,25 @@
<div class="info-card">
<div class="info-card__avatar">&#x1F464;</div>
<div class="info-card__body">
<div class="info-card__name">&#x5F20;&#x4E09;</div>
<div class="info-card__id">ID: 98369</div>
</div>
<div class="info-card__right">
<div class="info-card__label">&#x63A8;&#x8350;&#x70ED;&#x91CF;</div>
<div class="info-card__value">720 <span class="info-card__unit">&#x5343;&#x5361;</span></div>
<div class="info-card__line" style="justify-content:space-between;margin-bottom:0;">
<span class="info-card__name">&#x5F20;&#x4E09;</span>
<span class="info-card__id">&#x7F16;&#x53F7;: 98369</span>
</div>
</div>
</div>
<div class="info-card info-card--dish" id="dishInfoCard">
<div class="info-card__emoji" id="dishEmoji"></div>
<div class="info-card__body">
<div class="info-card__dish-name">&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;</div>
<div class="info-card__dish-detail">&#x5355;&#x4EF7; <em>5</em> &#x5143;/100&#x514B; &nbsp;|&nbsp; &#x70ED;&#x91CF; <em>158.66</em> &#x5343;&#x5361;/100&#x514B;</div>
<div class="info-card__dish-line">
<span class="info-card__dish-name">&#x5BAB;&#x4FDD;&#x9E21;&#x4E01;</span>
<span class="info-card__dish-price">5<span class="price-unit">&#x5143;/100g</span></span>
</div>
</div>
</div>
</div>
<!-- 营养标题行 -->
<div class="nutrition-header-row">
<span class="n-title">&#x1F4CA; &#x672C;&#x9910;&#x6B21;&#x6444;&#x5165;</span>
<span class="n-title">&#x1F4CA; &#x672C;&#x9910;&#x6B21;&#x6444;&#x5165;<span class="n-title-hint">&#xFF08;&#x63A8;&#x8350;&#x70ED;&#x91CF; 2000~2500 &#x5343;&#x5361;&#xFF09;</span></span>
<span>
<span class="n-meal">&#x5F53;&#x524D;&#x9910;&#x6B21;&#xFF1A;&#x65E9;&#x9910;</span>
<span class="n-time">06:00 ~ 10:19</span>
@@ -478,7 +575,7 @@
<div class="pickup-footer">
<span class="lbl">&#x5408;&#x8BA1;</span>
<span class="val">756&#x514B;</span>
<span class="price-val">20.90&#x5143;</span>
<span class="price-val">20.90</span>
</div>
</div>
</div>
@@ -489,6 +586,11 @@
</div>
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
/**
* 取餐界面交互逻辑
*/
@@ -527,24 +629,6 @@
}, t);
}
// 拟真食物图片
function dishFoodSVG(w, h, colors) {
var id = 'dg';
return '<svg xmlns="http://www.w3.org/2000/svg" width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '">' +
'<defs><linearGradient id="' + id + '" x1="0" y1="0" x2="1" y2="1">' +
'<stop offset="0%" stop-color="' + colors[0] + '"/>' +
'<stop offset="50%" stop-color="' + colors[1] + '"/>' +
'<stop offset="100%" stop-color="' + colors[2] + '"/></linearGradient></defs>' +
'<rect width="' + w + '" height="' + h + '" fill="url(#' + id + ')"/>' +
'<ellipse cx="' + (w*0.4) + '" cy="' + (h*0.45) + '" rx="' + (w*0.3) + '" ry="' + (h*0.25) + '" fill="rgba(255,255,255,0.08)"/>' +
'<ellipse cx="' + (w*0.6) + '" cy="' + (h*0.55) + '" rx="' + (w*0.25) + '" ry="' + (h*0.2) + '" fill="rgba(0,0,0,0.1)"/>' +
'<ellipse cx="' + (w*0.35) + '" cy="' + (h*0.35) + '" rx="' + (w*0.12) + '" ry="' + (h*0.1) + '" fill="rgba(255,255,255,0.15)"/>' +
'</svg>';
}
// 宫保鸡丁:暖橙金
document.getElementById('dishEmoji').innerHTML = dishFoodSVG(48, 48, ['#C87030', '#E8A040', '#D08028']);
</script>
</body>
</html>
@@ -471,6 +471,11 @@
<!-- ===== 交互逻辑 ===== -->
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
var toast = document.getElementById('toast');
/**
@@ -270,6 +270,11 @@ body {
</div>
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
/**
* 餐品采样界面交互逻辑
*/
@@ -303,6 +303,11 @@ body {
</div>
<script>
/* ===== 返回按钮:优先 history.back(),无历史记录时兜底跳模块导航 ===== */
document.getElementById('backBtn').addEventListener('click', function() {
if (history.length > 1) { history.back(); }
else { window.location.href = 'index.html'; }
});
/**
* 采样历史页面交互逻辑
*/
@@ -105,15 +105,10 @@
<div class="card__title">取餐界面(单屏)</div>
<div class="card__desc">取餐确认、订单生成与营养报告</div>
</a>
<a class="card" href="03-meal-pickup-dual-large.html">
<a class="card" href="03-meal-pickup-dual.html">
<span class="card__icon">&#x1F5A5;&#xFE0F;</span>
<div class="card__title">取餐界面(双屏·大屏</div>
<div class="card__desc">大屏取餐信息展示、用户信息与取餐记录</div>
</a>
<a class="card" href="03-meal-pickup-dual-small.html">
<span class="card__icon">&#x1F4CA;</span>
<div class="card__title">取餐界面(双屏·小屏)</div>
<div class="card__desc">小屏营养摄入柱状图与推荐热量展示</div>
<div class="card__title">取餐界面(双屏)</div>
<div class="card__desc">大屏取餐信息+右小屏营养摄入柱状图同页展示</div>
</a>
<a class="card" href="04-settings.html">
<span class="card__icon">&#x2699;&#xFE0F;</span>
@@ -0,0 +1,751 @@
<!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; }
/* 外层视口:全屏深色背景,承载居中 PAD 外壳 */
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;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* ===== 顶部导航栏 ===== */
.top-bar {
display: flex;
align-items: center;
height: 44px;
background: #1a2b4a;
padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
cursor: pointer;
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__meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
/* ===== 主内容:左右两列 ===== */
.main-area {
flex: 1;
display: grid;
grid-template-columns: 1fr 360px;
gap: 0;
overflow: hidden;
}
/* ===== 左列:人脸识别区 ===== */
.camera-col {
display: flex;
flex-direction: column;
padding: 28px 28px 20px;
gap: 18px;
overflow: hidden;
}
.col-label {
font-size: 12px;
color: rgba(255, 255, 255, 0.4);
font-weight: 500;
letter-spacing: 1.5px;
display: flex;
align-items: center;
gap: 8px;
}
.col-label__bar {
width: 3px;
height: 12px;
background: #4a90d9;
border-radius: 2px;
}
/* 摄像头预览框 */
.camera-frame {
flex: 1;
background: #050a1a;
border-radius: 16px;
position: relative;
border: 1px solid rgba(74, 144, 217, 0.2);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
min-height: 0;
}
/* 背景径向渐变模拟摄像头画面 */
.camera-frame__bg {
position: absolute;
inset: 0;
background:
radial-gradient(circle at 50% 40%, rgba(74, 144, 217, 0.12) 0%, transparent 60%),
radial-gradient(circle at 50% 100%, rgba(74, 144, 217, 0.06) 0%, transparent 70%);
}
/* 十字虚线参考线 */
.camera-frame__cross-h, .camera-frame__cross-v {
position: absolute;
pointer-events: none;
z-index: 2;
}
.camera-frame__cross-h {
top: 50%; left: 12%; right: 12%;
height: 1px;
border-top: 1px dashed rgba(74, 144, 217, 0.25);
}
.camera-frame__cross-v {
left: 50%; top: 15%; bottom: 15%;
width: 1px;
border-left: 1px dashed rgba(74, 144, 217, 0.25);
}
/* 四角识别标记 */
.corner {
position: absolute;
width: 24px;
height: 24px;
z-index: 3;
transition: all 0.3s;
}
.corner--tl { top: 18px; left: 18px; border-top: 2px solid #4a90d9; border-left: 2px solid #4a90d9; }
.corner--tr { top: 18px; right: 18px; border-top: 2px solid #4a90d9; border-right: 2px solid #4a90d9; }
.corner--bl { bottom: 18px; left: 18px; border-bottom: 2px solid #4a90d9; border-left: 2px solid #4a90d9; }
.corner--br { bottom: 18px; right: 18px; border-bottom: 2px solid #4a90d9; border-right: 2px solid #4a90d9; }
/* 识别中四角变绿 */
.camera-frame.success .corner { border-color: #52c41a; }
/* 人脸头像占位(模拟检测到人脸) */
.face-placeholder {
width: 160px;
height: 160px;
border-radius: 50%;
background: radial-gradient(circle at 50% 40%, rgba(74, 144, 217, 0.25), rgba(74, 144, 217, 0.05) 70%);
border: 2px solid rgba(74, 144, 217, 0.5);
display: flex;
align-items: center;
justify-content: center;
font-size: 64px;
color: rgba(255, 255, 255, 0.6);
position: relative;
z-index: 4;
box-shadow: 0 0 40px rgba(74, 144, 217, 0.3);
}
/* 识别中扫描线 */
.scan-line {
position: absolute;
left: 50%;
top: 50%;
width: 180px;
height: 2px;
background: linear-gradient(90deg, transparent, #4a90d9 50%, transparent);
transform: translate(-50%, -50%);
z-index: 5;
box-shadow: 0 0 8px rgba(74, 144, 217, 0.6);
opacity: 0;
transition: opacity 0.3s;
}
.camera-frame.scanning .scan-line {
opacity: 1;
animation: scanMove 1.8s ease-in-out infinite;
}
@keyframes scanMove {
0%, 100% { transform: translate(-50%, -80px); }
50% { transform: translate(-50%, 80px); }
}
/* 识别状态文字 */
.camera-status {
position: absolute;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 10px;
padding: 8px 18px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid rgba(74, 144, 217, 0.35);
border-radius: 20px;
font-size: 13px;
color: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(8px);
z-index: 6;
white-space: nowrap;
}
.camera-status__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #4a90d9;
box-shadow: 0 0 8px #4a90d9;
animation: pulse 1.4s ease-in-out infinite;
}
.camera-frame.success .camera-status {
border-color: rgba(82, 196, 26, 0.45);
color: #4ade80;
}
.camera-frame.success .camera-status__dot {
background: #52c41a;
box-shadow: 0 0 8px #52c41a;
animation: none;
}
.camera-frame.error .camera-status {
border-color: rgba(245, 34, 45, 0.45);
color: #ff6b6b;
}
.camera-frame.error .camera-status__dot {
background: #f5222d;
box-shadow: 0 0 8px #f5222d;
animation: none;
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(1.2); }
}
/* 识别成功后展示的姓名浮层 */
.face-success-overlay {
position: absolute;
inset: 0;
background: rgba(5, 10, 26, 0.85);
backdrop-filter: blur(4px);
display: none;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 16px;
z-index: 10;
animation: fadeIn 0.3s ease;
}
.camera-frame.success .face-success-overlay { display: flex; }
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.success-avatar {
width: 110px;
height: 110px;
border-radius: 50%;
background: linear-gradient(135deg, #52c41a 0%, #0AC4A8 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
color: #fff;
font-weight: 600;
box-shadow: 0 8px 32px rgba(82, 196, 26, 0.4);
}
.success-info { text-align: center; }
.success-name {
font-size: 22px;
font-weight: 700;
color: #fff;
margin-bottom: 4px;
}
.success-meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
letter-spacing: 0.5px;
}
.success-tip {
font-size: 12px;
color: #4ade80;
margin-top: 8px;
display: flex;
align-items: center;
gap: 6px;
}
/* 左列底部说明栏 */
.tip-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 10px;
}
.tip-bar__left {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: rgba(255, 255, 255, 0.65);
}
.tip-bar__icon {
font-size: 14px;
}
.tip-bar__right {
font-size: 11px;
color: rgba(255, 255, 255, 0.4);
font-family: Menlo, Consolas, monospace;
}
/* ===== 右列:班次信息 + 操作入口 ===== */
.info-col {
background: rgba(26, 43, 74, 0.3);
border-left: 1px solid rgba(255, 255, 255, 0.06);
padding: 28px 24px;
display: flex;
flex-direction: column;
gap: 16px;
overflow-y: auto;
scrollbar-width: none;
}
.info-col::-webkit-scrollbar { display: none; }
/* 大时钟 */
.clock-card {
text-align: center;
padding: 20px 0 8px;
}
.clock-card__time {
font-size: 44px;
font-weight: 200;
color: #fff;
font-family: Menlo, Consolas, "Courier New", monospace;
line-height: 1;
letter-spacing: 2px;
}
.clock-card__date {
font-size: 13px;
color: rgba(255, 255, 255, 0.5);
margin-top: 8px;
}
/* 班次信息卡 */
.shift-card {
background: #1a2b4a;
border: 1px solid rgba(74, 144, 217, 0.25);
border-radius: 10px;
padding: 14px 16px;
}
.shift-card__title {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
letter-spacing: 1px;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.shift-card__title::before {
content: "";
width: 3px;
height: 11px;
background: #4a90d9;
border-radius: 2px;
}
.shift-card__row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 0;
font-size: 13px;
}
.shift-card__row + .shift-card__row {
border-top: 1px dashed rgba(255, 255, 255, 0.06);
}
.shift-card__label {
color: rgba(255, 255, 255, 0.55);
font-size: 12px;
}
.shift-card__value {
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
}
.meal-tag {
font-size: 10px;
line-height: 1;
padding: 4px 8px;
border-radius: 9px;
font-weight: 600;
letter-spacing: 0.3px;
}
.meal-tag--breakfast {
background: rgba(250, 140, 22, 0.18);
color: #fb923c;
border: 1px solid rgba(250, 140, 22, 0.35);
}
.meal-tag--lunch {
background: rgba(37, 99, 235, 0.18);
color: #60a5fa;
border: 1px solid rgba(37, 99, 235, 0.35);
}
.meal-tag--dinner {
background: rgba(34, 197, 94, 0.18);
color: #4ade80;
border: 1px solid rgba(34, 197, 94, 0.35);
}
/* 设备状态卡 */
.device-card {
background: #1a2b4a;
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 10px;
padding: 14px 16px;
}
.device-card__row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 0;
font-size: 12px;
}
.device-card__label {
color: rgba(255, 255, 255, 0.55);
}
.device-card__value {
color: rgba(255, 255, 255, 0.85);
display: flex;
align-items: center;
gap: 5px;
}
.status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #52c41a;
box-shadow: 0 0 6px #52c41a;
}
.status-dot--offline { background: #f5222d; box-shadow: 0 0 6px #f5222d; }
/* 快捷入口 */
.quick-entry {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: auto;
padding-top: 10px;
}
.quick-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 14px 10px;
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 10px;
text-decoration: none;
color: rgba(255, 255, 255, 0.75);
font-size: 11px;
transition: all 0.2s;
cursor: pointer;
}
.quick-btn:hover {
background: rgba(74, 144, 217, 0.08);
border-color: rgba(74, 144, 217, 0.35);
color: #fff;
transform: translateY(-1px);
}
.quick-btn__icon {
font-size: 22px;
}
/* 底部:登录失败次数提示 */
.fail-counter {
display: none;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px 12px;
background: rgba(245, 34, 45, 0.1);
border: 1px solid rgba(245, 34, 45, 0.3);
border-radius: 8px;
font-size: 12px;
color: #ff6b6b;
}
.fail-counter.show { display: flex; }
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" href="index.html">&#x25C0; 返回</a>
<span class="top-bar__title">收银员登录</span>
<span class="top-bar__meta" id="topMeta">2026-08-06 周四</span>
</div>
<!-- 主内容 -->
<div class="main-area">
<!-- 左列:人脸识别区 -->
<div class="camera-col">
<div class="col-label">
<span class="col-label__bar"></span>
人脸识别登录
</div>
<div class="camera-frame" id="cameraFrame">
<div class="camera-frame__bg"></div>
<div class="camera-frame__cross-h"></div>
<div class="camera-frame__cross-v"></div>
<div class="corner corner--tl"></div>
<div class="corner corner--tr"></div>
<div class="corner corner--bl"></div>
<div class="corner corner--br"></div>
<!-- 人脸占位 -->
<div class="face-placeholder">&#x1F464;</div>
<!-- 扫描线 -->
<div class="scan-line"></div>
<!-- 状态提示 -->
<div class="camera-status">
<span class="camera-status__dot"></span>
<span id="statusText">请面向摄像头进行识别</span>
</div>
<!-- 识别成功浮层 -->
<div class="face-success-overlay">
<div class="success-avatar"></div>
<div class="success-info">
<div class="success-name">张三</div>
<div class="success-meta">工号:CS001 · 一楼结算台</div>
<div class="success-tip">&#x2705; 识别成功,正在登录...</div>
</div>
</div>
</div>
<div class="tip-bar">
<div class="tip-bar__left">
<span class="tip-bar__icon">&#x1F4F7;</span>
<span>请保持面部正对摄像头,光线充足,摘掉口罩/墨镜</span>
</div>
<div class="tip-bar__right">设备:CHK-001</div>
</div>
<div class="fail-counter" id="failCounter">
&#x26A0;&#xFE0F; 识别失败,今日剩余尝试次数:<span id="failCount">3</span>
</div>
</div>
<!-- 右列:班次信息 + 操作入口 -->
<div class="info-col">
<!-- 大时钟 -->
<div class="clock-card">
<div class="clock-card__time" id="clockTime">12:30:45</div>
<div class="clock-card__date" id="clockDate">2026-08-06 周四</div>
</div>
<!-- 班次信息卡 -->
<div class="shift-card">
<div class="shift-card__title">当前班次</div>
<div class="shift-card__row">
<span class="shift-card__label">所属食堂</span>
<span class="shift-card__value">数味餐厅</span>
</div>
<div class="shift-card__row">
<span class="shift-card__label">餐次</span>
<span class="meal-tag meal-tag--lunch" id="mealTag">午餐</span>
</div>
<div class="shift-card__row">
<span class="shift-card__label">餐线</span>
<span class="shift-card__value">一楼 A 区 2 号餐线</span>
</div>
<div class="shift-card__row">
<span class="shift-card__label">班次时段</span>
<span class="shift-card__value">11:00 - 14:00</span>
</div>
</div>
<!-- 设备状态卡 -->
<div class="device-card">
<div class="shift-card__title" style="margin-bottom:8px;">设备状态</div>
<div class="device-card__row">
<span class="device-card__label">网络连接</span>
<span class="device-card__value"><span class="status-dot"></span>正常</span>
</div>
<div class="device-card__row">
<span class="device-card__label">摄像头</span>
<span class="device-card__value"><span class="status-dot"></span>就绪</span>
</div>
<div class="device-card__row">
<span class="device-card__label">小票打印机</span>
<span class="device-card__value"><span class="status-dot"></span>就绪</span>
</div>
<div class="device-card__row">
<span class="device-card__label">扫码器</span>
<span class="device-card__value"><span class="status-dot"></span>就绪</span>
</div>
</div>
<!-- 快捷入口 -->
<div class="quick-entry">
<a class="quick-btn" href="javascript:void(0)" onclick="showToast('请联系管理员在后台开启维护模式')">
<span class="quick-btn__icon">&#x1F527;</span>
<span>管理员设置</span>
</a>
<a class="quick-btn" href="javascript:void(0)" onclick="showToast('已上报故障,运维人员将尽快处理')">
<span class="quick-btn__icon">&#x1F4E1;</span>
<span>故障报修</span>
</a>
</div>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast"></div>
<style>
/* 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--success { background: rgba(82, 196, 26, 0.92); }
</style>
<script>
/* ==================== 实时时钟 ==================== */
function updateClock() {
var now = new Date();
var hh = String(now.getHours()).padStart(2, '0');
var mm = String(now.getMinutes()).padStart(2, '0');
var ss = String(now.getSeconds()).padStart(2, '0');
var timeStr = hh + ':' + mm + ':' + ss;
var year = now.getFullYear();
var month = String(now.getMonth() + 1).padStart(2, '0');
var date = String(now.getDate()).padStart(2, '0');
var weekDay = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][now.getDay()];
var dateStr = year + '-' + month + '-' + date + ' ' + weekDay;
document.getElementById('clockTime').textContent = timeStr;
document.getElementById('clockDate').textContent = dateStr;
document.getElementById('topMeta').textContent = dateStr;
}
/* 根据当前小时自动判断餐次 */
function detectMealType() {
var hour = new Date().getHours();
var mealTag = document.getElementById('mealTag');
if (hour >= 6 && hour < 10) {
mealTag.className = 'meal-tag meal-tag--breakfast';
mealTag.textContent = '早餐';
} else if (hour >= 10 && hour < 14) {
mealTag.className = 'meal-tag meal-tag--lunch';
mealTag.textContent = '午餐';
} else if (hour >= 16 && hour < 21) {
mealTag.className = 'meal-tag meal-tag--dinner';
mealTag.textContent = '晚餐';
} else {
mealTag.className = 'meal-tag meal-tag--lunch';
mealTag.textContent = '非餐时段';
}
}
/* ==================== 人脸识别流程模拟 ==================== */
var frame = document.getElementById('cameraFrame');
var statusText = document.getElementById('statusText');
var failCounter = document.getElementById('failCounter');
var failCountEl = document.getElementById('failCount');
var failCount = 3;
function startRecognition() {
/* 阶段 1:提示用户 */
frame.className = 'camera-frame';
statusText.textContent = '请面向摄像头进行识别';
/* 阶段 2:1.5s 后开始扫描 */
setTimeout(function() {
frame.classList.add('scanning');
statusText.textContent = '人脸识别中...';
}, 1500);
/* 阶段 3:4s 后识别成功,1.5s 后跳转待机页 */
setTimeout(function() {
frame.classList.remove('scanning');
frame.classList.add('success');
statusText.textContent = '识别成功';
setTimeout(function() {
window.location.href = '02-standby.html';
}, 1500);
}, 4000);
}
/* ==================== Toast ==================== */
function showToast(msg, type) {
var el = document.getElementById('toast');
el.textContent = msg;
el.className = 'toast';
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'); }, 2200);
}
/* ==================== 初始化 ==================== */
updateClock();
detectMealType();
setInterval(updateClock, 1000);
/* 自动启动人脸识别模拟 */
setTimeout(startRecognition, 800);
</script>
</body>
</html>
@@ -0,0 +1,495 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: #0e1326;
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.top-bar {
display: flex;
align-items: center;
height: 44px;
background: #1a2b4a;
padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
cursor: pointer;
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__meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
/* 主内容 */
.main-area {
flex: 1;
display: flex;
flex-direction: column;
padding: 32px 56px 28px;
overflow: hidden;
}
/* 顶部欢迎区 */
.welcome {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 24px;
}
.welcome__left { display: flex; flex-direction: column; gap: 6px; }
.welcome__hello {
font-size: 28px;
font-weight: 600;
color: #fff;
display: flex;
align-items: center;
gap: 10px;
}
.welcome__name { color: #4a90d9; }
.welcome__sub {
font-size: 13px;
color: rgba(255, 255, 255, 0.5);
}
.welcome__right {
display: flex;
gap: 12px;
align-items: center;
}
.cashier-info {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px 6px 6px;
background: rgba(26, 43, 74, 0.6);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 22px;
}
.cashier-info__avatar {
width: 28px;
height: 28px;
border-radius: 50%;
background: linear-gradient(135deg, #4a90d9, #0AC4A8);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
}
.cashier-info__text { font-size: 12px; color: rgba(255, 255, 255, 0.85); }
.logout-btn {
padding: 6px 14px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 18px;
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
text-decoration: none;
}
.logout-btn:hover {
background: rgba(245, 34, 45, 0.15);
border-color: rgba(245, 34, 45, 0.35);
color: #ff6b6b;
}
/* 中央:核心动作区 */
.hero {
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
margin-bottom: 24px;
min-height: 0;
}
/* 左:大时钟 + 待机动作 */
.hero__left {
display: flex;
flex-direction: column;
justify-content: center;
gap: 24px;
padding: 28px 32px;
background: linear-gradient(135deg, rgba(74, 144, 217, 0.12) 0%, rgba(26, 43, 74, 0.4) 100%);
border: 1px solid rgba(74, 144, 217, 0.2);
border-radius: 18px;
}
.big-clock {
font-size: 76px;
font-weight: 200;
font-family: Menlo, Consolas, "Courier New", monospace;
line-height: 1;
letter-spacing: 3px;
color: #fff;
}
.big-date {
font-size: 16px;
color: rgba(255, 255, 255, 0.55);
display: flex;
align-items: center;
gap: 10px;
}
.meal-tag-large {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border-radius: 16px;
font-size: 13px;
font-weight: 600;
}
.meal-tag-large--lunch {
background: rgba(37, 99, 235, 0.18);
color: #60a5fa;
border: 1px solid rgba(37, 99, 235, 0.35);
}
/* 开始结算按钮 */
.start-checkout {
display: flex;
align-items: center;
justify-content: center;
gap: 14px;
padding: 22px 28px;
background: linear-gradient(135deg, #4a90d9, #3a7bc8);
border: none;
border-radius: 14px;
cursor: pointer;
transition: all 0.25s;
text-decoration: none;
box-shadow: 0 8px 24px rgba(74, 144, 217, 0.3);
position: relative;
overflow: hidden;
}
.start-checkout:hover {
transform: translateY(-2px);
box-shadow: 0 12px 32px rgba(74, 144, 217, 0.45);
}
.start-checkout:active { transform: scale(0.99); }
.start-checkout__icon {
font-size: 32px;
}
.start-checkout__text {
text-align: left;
display: flex;
flex-direction: column;
gap: 2px;
}
.start-checkout__title {
font-size: 20px;
font-weight: 700;
color: #fff;
}
.start-checkout__desc {
font-size: 12px;
color: rgba(255, 255, 255, 0.8);
}
/* 呼吸灯 */
.start-checkout::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255,255,255,0.15) 50%, transparent 70%);
transform: translateX(-100%);
animation: shimmer 2.5s ease-in-out infinite;
}
@keyframes shimmer {
0%, 100% { transform: translateX(-100%); }
50% { transform: translateX(100%); }
}
/* 右:今日数据预览 */
.hero__right {
display: flex;
flex-direction: column;
padding: 22px 24px;
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 18px;
}
.panel-title {
font-size: 13px;
color: rgba(255, 255, 255, 0.55);
letter-spacing: 1px;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
}
.panel-title::before {
content: "";
width: 3px;
height: 13px;
background: #4a90d9;
border-radius: 2px;
}
.kpi-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
flex: 1;
}
.kpi-cell {
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 255, 255, 0.04);
border-radius: 10px;
padding: 14px 16px;
display: flex;
flex-direction: column;
gap: 6px;
}
.kpi-cell__label {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
}
.kpi-cell__value {
font-size: 22px;
font-weight: 700;
color: #fff;
display: flex;
align-items: baseline;
gap: 4px;
}
.kpi-cell__unit {
font-size: 12px;
font-weight: 400;
color: rgba(255, 255, 255, 0.55);
}
.kpi-cell__value--green { color: #4ade80; }
.kpi-cell__value--gold { color: #fbbf24; }
.kpi-cell__hint {
font-size: 10px;
color: rgba(255, 255, 255, 0.35);
}
/* 底部:功能入口横排 */
.bottom-entry {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 14px;
}
.entry-card {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 18px;
background: rgba(26, 43, 74, 0.5);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 12px;
text-decoration: none;
transition: all 0.2s;
cursor: pointer;
}
.entry-card:hover {
transform: translateY(-2px);
background: rgba(74, 144, 217, 0.1);
border-color: rgba(74, 144, 217, 0.35);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.entry-card__icon {
width: 40px;
height: 40px;
border-radius: 10px;
background: rgba(74, 144, 217, 0.15);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
flex-shrink: 0;
}
.entry-card__icon--gold { background: rgba(251, 191, 36, 0.15); }
.entry-card__icon--purple { background: rgba(168, 85, 247, 0.15); }
.entry-card__icon--green { background: rgba(82, 196, 26, 0.15); }
.entry-card__text { display: flex; flex-direction: column; gap: 2px; }
.entry-card__title {
font-size: 14px;
font-weight: 600;
color: #fff;
}
.entry-card__desc {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
}
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" href="index.html">&#x25C0; 返回主页</a>
<span class="top-bar__title">结算台待机</span>
<span class="top-bar__meta" id="topMeta">2026-08-06 周四</span>
</div>
<!-- 主内容 -->
<div class="main-area">
<!-- 顶部欢迎区 -->
<div class="welcome">
<div class="welcome__left">
<div class="welcome__hello">
&#x1F44B; 中午好,<span class="welcome__name">张三</span>
</div>
<div class="welcome__sub">数味餐厅 · 一楼 A 区 2 号餐线 · 等待顾客取餐</div>
</div>
<div class="welcome__right">
<div class="cashier-info">
<div class="cashier-info__avatar"></div>
<div class="cashier-info__text">CS001 · 张三</div>
</div>
<a class="logout-btn" href="01-login.html" onclick="return confirm('确定退出登录吗?');">退出登录</a>
</div>
</div>
<!-- 中央核心动作区 -->
<div class="hero">
<!-- 左:大时钟 + 开始结算 -->
<div class="hero__left">
<div>
<div class="big-clock" id="bigClock">12:30:45</div>
<div class="big-date" id="bigDate">
2026-08-06 周四
<span class="meal-tag-large meal-tag-large--lunch" id="mealTag">&#x1F96A; 午餐时段</span>
</div>
</div>
<a class="start-checkout" href="03-checkout.html">
<span class="start-checkout__icon">&#x1F6CD;&#xFE0F;</span>
<span class="start-checkout__text">
<span class="start-checkout__title">开始结算</span>
<span class="start-checkout__desc">顾客取餐完成,点击进入结算流程</span>
</span>
</a>
</div>
<!-- 右:今日数据预览 -->
<div class="hero__right">
<div class="panel-title">午餐餐次数据 · 11:00 - 14:00</div>
<div class="kpi-grid">
<div class="kpi-cell">
<div class="kpi-cell__label">本餐次营收</div>
<div class="kpi-cell__value kpi-cell__value--green">&#xFFE5;2,614<span class="kpi-cell__unit">.50</span></div>
<div class="kpi-cell__hint">较昨日午餐 +12.5%</div>
</div>
<div class="kpi-cell">
<div class="kpi-cell__label">本餐次订单</div>
<div class="kpi-cell__value">96<span class="kpi-cell__unit"></span></div>
<div class="kpi-cell__hint">较昨日午餐 -36</div>
</div>
<div class="kpi-cell">
<div class="kpi-cell__label">客单价</div>
<div class="kpi-cell__value kpi-cell__value--gold">&#xFFE5;27.23</div>
<div class="kpi-cell__hint">较昨日午餐 +0.85</div>
</div>
<div class="kpi-cell">
<div class="kpi-cell__label">平均菜品数</div>
<div class="kpi-cell__value">3.2<span class="kpi-cell__unit">道/单</span></div>
<div class="kpi-cell__hint">较昨日午餐 +0.3 道</div>
</div>
</div>
</div>
</div>
<!-- 底部功能入口 -->
<div class="bottom-entry">
<a class="entry-card" href="05-orders.html">
<div class="entry-card__icon">&#x1F4CB;</div>
<div class="entry-card__text">
<div class="entry-card__title">订单列表</div>
<div class="entry-card__desc">今日订单查询/退款</div>
</div>
</a>
<a class="entry-card" href="07-statistics.html">
<div class="entry-card__icon entry-card__icon--purple">&#x1F4CA;</div>
<div class="entry-card__text">
<div class="entry-card__title">运营统计</div>
<div class="entry-card__desc">今日数据可视化</div>
</div>
</a>
<a class="entry-card" href="09-print-receipt.html">
<div class="entry-card__icon entry-card__icon--gold">&#x1F5A8;&#xFE0F;</div>
<div class="entry-card__text">
<div class="entry-card__title">小票打印</div>
<div class="entry-card__desc">补打/重打订单小票</div>
</div>
</a>
<a class="entry-card" href="javascript:void(0)" onclick="alert('设置功能待开发')">
<div class="entry-card__icon entry-card__icon--green">&#x2699;&#xFE0F;</div>
<div class="entry-card__text">
<div class="entry-card__title">设备设置</div>
<div class="entry-card__desc">本机参数/网络/音量</div>
</div>
</a>
</div>
</div>
</div>
<script>
/* 实时时钟 */
function updateClock() {
var now = new Date();
var hh = String(now.getHours()).padStart(2, '0');
var mm = String(now.getMinutes()).padStart(2, '0');
var ss = String(now.getSeconds()).padStart(2, '0');
var timeStr = hh + ':' + mm + ':' + ss;
var year = now.getFullYear();
var month = String(now.getMonth() + 1).padStart(2, '0');
var date = String(now.getDate()).padStart(2, '0');
var weekDay = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][now.getDay()];
var dateStr = year + '-' + month + '-' + date + ' ' + weekDay;
document.getElementById('bigClock').textContent = timeStr;
document.getElementById('bigDate').firstChild.textContent = ' ' + dateStr + ' ';
document.getElementById('topMeta').textContent = dateStr;
}
updateClock();
setInterval(updateClock, 1000);
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,412 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: linear-gradient(180deg, #0e1326 0%, #0a1f2e 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.top-bar {
display: flex;
align-items: center;
height: 44px;
background: #1a2b4a;
padding: 0 20px;
flex-shrink: 0;
}
.top-bar__title {
flex: 1;
text-align: center;
font-size: 15px;
font-weight: 600;
color: rgba(255, 255, 255, 0.85);
}
.top-bar__meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
.top-bar__left { width: 100px; }
/* 主内容 */
.main-area {
flex: 1;
display: grid;
grid-template-columns: 1.2fr 1fr;
overflow: hidden;
}
/* ============ 左:成功动画 + 金额展示 ============ */
.success-col {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px;
gap: 28px;
border-right: 1px solid rgba(255, 255, 255, 0.06);
}
.success-icon {
width: 120px;
height: 120px;
border-radius: 50%;
background: linear-gradient(135deg, #52c41a, #0AC4A8);
display: flex;
align-items: center;
justify-content: center;
font-size: 60px;
color: #fff;
box-shadow: 0 12px 40px rgba(82, 196, 26, 0.5), 0 0 0 8px rgba(82, 196, 26, 0.1);
animation: bounceIn 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
@keyframes bounceIn {
0% { transform: scale(0); opacity: 0; }
60% { transform: scale(1.1); opacity: 1; }
100% { transform: scale(1); }
}
.success-title {
font-size: 32px;
font-weight: 700;
color: #fff;
text-align: center;
}
.success-amount {
text-align: center;
}
.success-amount__label {
font-size: 14px;
color: rgba(255, 255, 255, 0.5);
margin-bottom: 8px;
}
.success-amount__value {
font-size: 64px;
font-weight: 700;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
line-height: 1;
}
.success-pay-method {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
background: rgba(82, 196, 26, 0.15);
border: 1px solid rgba(82, 196, 26, 0.35);
border-radius: 18px;
font-size: 12px;
color: #4ade80;
margin-top: 10px;
}
/* 订单基础信息 */
.success-meta {
width: 100%;
max-width: 380px;
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 12px;
padding: 14px 18px;
}
.meta-row {
display: flex;
justify-content: space-between;
padding: 6px 0;
font-size: 12px;
}
.meta-row + .meta-row { border-top: 1px dashed rgba(255, 255, 255, 0.06); }
.meta-row__label { color: rgba(255, 255, 255, 0.55); }
.meta-row__value { color: rgba(255, 255, 255, 0.9); font-weight: 600; }
/* ============ 右:操作 + 营养摘要 ============ */
.action-col {
display: flex;
flex-direction: column;
padding: 28px 28px 24px;
gap: 18px;
overflow-y: auto;
scrollbar-width: none;
}
.action-col::-webkit-scrollbar { display: none; }
.section-label {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
letter-spacing: 1px;
display: flex;
align-items: center;
gap: 6px;
}
.section-label::before {
content: "";
width: 3px;
height: 11px;
background: #4a90d9;
border-radius: 2px;
}
/* 营养摘要卡 */
.nutrition-card {
background: linear-gradient(135deg, rgba(10, 196, 168, 0.12), rgba(74, 144, 217, 0.08));
border: 1px solid rgba(10, 196, 168, 0.3);
border-radius: 14px;
padding: 16px;
}
.nutrition-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.nutrition-head__title {
font-size: 13px;
color: rgba(255, 255, 255, 0.85);
font-weight: 600;
}
.nutrition-score {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 10px;
background: rgba(251, 191, 36, 0.15);
border: 1px solid rgba(251, 191, 36, 0.3);
border-radius: 14px;
font-size: 12px;
color: #fbbf24;
font-weight: 700;
}
.nutrition-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.nutrition-item {
text-align: center;
padding: 10px 4px;
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.nutrition-item__label {
font-size: 10px;
color: rgba(255, 255, 255, 0.5);
margin-bottom: 4px;
}
.nutrition-item__value {
font-size: 18px;
font-weight: 700;
color: #fff;
font-family: Menlo, Consolas, monospace;
}
.nutrition-item__unit {
font-size: 10px;
color: rgba(255, 255, 255, 0.4);
font-weight: 400;
}
/* 操作按钮 */
.actions-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: auto;
}
.btn {
padding: 14px 12px;
border: none;
border-radius: 10px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
font-family: inherit;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
text-decoration: none;
}
.btn--primary {
background: linear-gradient(135deg, #52c41a, #0AC4A8);
color: #fff;
box-shadow: 0 6px 20px rgba(82, 196, 26, 0.35);
grid-column: 1 / -1;
}
.btn--primary:hover { transform: translateY(-1px); }
.btn--ghost {
background: rgba(255, 255, 255, 0.05);
color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(255, 255, 255, 0.12);
}
.btn--ghost:hover {
background: rgba(74, 144, 217, 0.1);
border-color: rgba(74, 144, 217, 0.35);
color: #fff;
}
.btn--gold {
background: rgba(251, 191, 36, 0.15);
color: #fbbf24;
border: 1px solid rgba(251, 191, 36, 0.35);
}
.btn--gold:hover {
background: rgba(251, 191, 36, 0.25);
}
/* 小票打印状态 */
.print-status {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 12px;
background: rgba(74, 144, 217, 0.1);
border: 1px solid rgba(74, 144, 217, 0.25);
border-radius: 8px;
font-size: 12px;
color: #60a5fa;
}
.print-status__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #52c41a;
box-shadow: 0 0 8px #52c41a;
}
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部导航 -->
<div class="top-bar">
<div class="top-bar__left"></div>
<span class="top-bar__title">支付成功</span>
<span class="top-bar__meta">2026-08-06 12:32:50</span>
</div>
<!-- 主内容 -->
<div class="main-area">
<!-- 左:成功动画 + 金额 -->
<div class="success-col">
<div class="success-icon">&#x2714;</div>
<div class="success-title">支付成功</div>
<div class="success-amount">
<div class="success-amount__label">实付金额</div>
<div class="success-amount__value">&#xFFE5;41.60</div>
<div class="success-pay-method">&#x1F4F1; 在线支付 · 微信支付</div>
</div>
<div class="success-meta">
<div class="meta-row">
<span class="meta-row__label">订单号</span>
<span class="meta-row__value">CO-20260806-031</span>
</div>
<div class="meta-row">
<span class="meta-row__label">餐线</span>
<span class="meta-row__value">一楼 A 区 2 号</span>
</div>
<div class="meta-row">
<span class="meta-row__label">收银员</span>
<span class="meta-row__value">张三 (CS001)</span>
</div>
<div class="meta-row">
<span class="meta-row__label">原价/优惠</span>
<span class="meta-row__value">&#xFFE5;46.60 / -&#xFFE5;5.00</span>
</div>
</div>
</div>
<!-- 右:操作 + 营养 -->
<div class="action-col">
<!-- 营养摘要 -->
<div>
<div class="section-label" style="margin-bottom:8px;">本餐营养摄入</div>
<div class="nutrition-card">
<div class="nutrition-head">
<span class="nutrition-head__title">&#x1F957; 营养摄入摘要</span>
<span class="nutrition-score">&#x2B50; 88 分</span>
</div>
<div class="nutrition-grid">
<div class="nutrition-item">
<div class="nutrition-item__label">热量</div>
<div class="nutrition-item__value">720<span class="nutrition-item__unit">kcal</span></div>
</div>
<div class="nutrition-item">
<div class="nutrition-item__label">蛋白质</div>
<div class="nutrition-item__value">35<span class="nutrition-item__unit">g</span></div>
</div>
<div class="nutrition-item">
<div class="nutrition-item__label">脂肪</div>
<div class="nutrition-item__value">28<span class="nutrition-item__unit">g</span></div>
</div>
<div class="nutrition-item">
<div class="nutrition-item__label">碳水</div>
<div class="nutrition-item__value">88<span class="nutrition-item__unit">g</span></div>
</div>
</div>
</div>
</div>
<!-- 小票打印状态 -->
<div class="print-status">
<span class="print-status__dot"></span>
<span>小票已自动打印(顾客可领取)</span>
</div>
<!-- 操作按钮 -->
<div class="actions-grid">
<a class="btn btn--primary" href="02-standby.html" style="grid-column:1 / -1;">
&#x1F6CD;&#xFE0F; 开始下一单
</a>
<a class="btn btn--gold" href="09-print-receipt.html">
&#x1F5A8;&#xFE0F; 重打小票
</a>
<a class="btn btn--ghost" href="06-order-detail.html">
&#x1F4C4; 订单详情
</a>
</div>
</div>
</div>
</div>
<script>
/* 8 秒后提示开始下一单 */
setTimeout(function() {
if (confirm('订单已完成,是否开始下一单?')) {
window.location.href = '02-standby.html';
}
}, 8000);
</script>
</body>
</html>
@@ -0,0 +1,598 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: #0e1326;
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.top-bar {
display: flex;
align-items: center;
height: 44px;
background: #1a2b4a;
padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
cursor: pointer;
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__meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
/* 主内容 */
.main-area {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 顶部筛选区 */
.filter-bar {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 20px;
background: rgba(26, 43, 74, 0.4);
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
flex-shrink: 0;
}
.date-range {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
background: rgba(74, 144, 217, 0.15);
border: 1px solid rgba(74, 144, 217, 0.35);
border-radius: 6px;
font-size: 12px;
color: #60a5fa;
font-weight: 600;
}
.filter-select {
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 6px 12px;
font-size: 12px;
color: rgba(255, 255, 255, 0.85);
font-family: inherit;
outline: none;
cursor: pointer;
}
.filter-select:focus { border-color: #4a90d9; }
.filter-bar__search {
flex: 1;
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
}
.filter-bar__search input {
flex: 1;
background: none;
border: none;
color: rgba(255, 255, 255, 0.85);
font-size: 12px;
outline: none;
font-family: inherit;
}
.filter-bar__search input::placeholder {
color: rgba(255, 255, 255, 0.35);
}
.filter-bar__stat {
display: flex;
gap: 14px;
padding: 6px 14px;
background: rgba(0, 0, 0, 0.2);
border-radius: 6px;
font-size: 11px;
color: rgba(255, 255, 255, 0.7);
}
.filter-bar__stat strong {
color: #4ade80;
font-family: Menlo, Consolas, monospace;
}
/* 订单列表 */
.order-list {
flex: 1;
overflow-y: auto;
padding: 14px 20px;
scrollbar-width: none;
}
.order-list::-webkit-scrollbar { display: none; }
.order-row {
display: grid;
grid-template-columns: 40px 1.3fr 70px 0.9fr 1.1fr 110px 95px 95px 130px;
gap: 10px;
align-items: center;
padding: 12px 14px;
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.04);
border-radius: 8px;
margin-bottom: 6px;
transition: all 0.15s;
cursor: pointer;
}
/* 表头 */
.order-head {
display: grid;
grid-template-columns: 40px 1.3fr 70px 0.9fr 1.1fr 110px 95px 95px 130px;
gap: 10px;
padding: 8px 14px;
font-size: 11px;
color: rgba(255, 255, 255, 0.45);
letter-spacing: 0.5px;
background: rgba(0, 0, 0, 0.2);
border-radius: 6px;
margin-bottom: 6px;
flex-shrink: 0;
}
.order-head > div { font-weight: 600; }
.order-head__amount { text-align: right; }
.order-head__actions { text-align: right; }
.order-row__amount { text-align: right; }
.order-row:hover {
background: rgba(74, 144, 217, 0.08);
border-color: rgba(74, 144, 217, 0.25);
}
.order-row.refunded { opacity: 0.55; }
.order-row__index {
font-size: 12px;
color: rgba(255, 255, 255, 0.4);
font-family: Menlo, Consolas, monospace;
text-align: center;
}
.order-row__id {
font-size: 13px;
color: #fff;
font-weight: 600;
font-family: Menlo, Consolas, monospace;
}
.order-row__sub {
font-size: 10px;
color: rgba(255, 255, 255, 0.4);
margin-top: 2px;
}
.meal-tag {
font-size: 10px;
line-height: 1;
padding: 4px 7px;
border-radius: 9px;
font-weight: 600;
letter-spacing: 0.3px;
text-align: center;
}
.meal-tag--breakfast {
background: rgba(250, 140, 22, 0.18);
color: #fb923c;
border: 1px solid rgba(250, 140, 22, 0.35);
}
.meal-tag--lunch {
background: rgba(37, 99, 235, 0.18);
color: #60a5fa;
border: 1px solid rgba(37, 99, 235, 0.35);
}
.meal-tag--dinner {
background: rgba(34, 197, 94, 0.18);
color: #4ade80;
border: 1px solid rgba(34, 197, 94, 0.35);
}
.order-row__items {
font-size: 12px;
color: rgba(255, 255, 255, 0.85);
font-weight: 600;
line-height: 1.4;
}
.order-row__items-hint {
font-size: 10px;
color: rgba(255, 255, 255, 0.4);
font-weight: 400;
margin-top: 2px;
}
.order-row__txn {
font-size: 11px;
color: rgba(255, 255, 255, 0.75);
font-family: Menlo, Consolas, monospace;
line-height: 1.4;
}
.order-row__pay-time {
font-size: 10px;
color: rgba(255, 255, 255, 0.4);
margin-top: 2px;
}
.order-row__amount {
font-size: 15px;
color: #0AC4A8;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
}
.order-row__pay-method {
display: flex;
align-items: center;
gap: 4px;
font-size: 11px;
color: rgba(255, 255, 255, 0.7);
}
.order-row__actions {
display: flex;
gap: 4px;
justify-content: flex-end;
}
.action-btn {
padding: 5px 8px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
color: rgba(255, 255, 255, 0.75);
font-size: 11px;
cursor: pointer;
transition: all 0.15s;
text-decoration: none;
white-space: nowrap;
}
.action-btn:hover {
background: rgba(74, 144, 217, 0.15);
border-color: rgba(74, 144, 217, 0.35);
color: #fff;
}
.action-btn--danger {
color: #ff6b6b;
border-color: rgba(245, 34, 45, 0.2);
}
.action-btn--danger:hover {
background: rgba(245, 34, 45, 0.15);
border-color: rgba(245, 34, 45, 0.45);
color: #ff6b6b;
}
.action-btn--gold {
color: #fbbf24;
border-color: rgba(251, 191, 36, 0.2);
}
.action-btn--gold:hover {
background: rgba(251, 191, 36, 0.15);
border-color: rgba(251, 191, 36, 0.45);
}
/* 状态标签 */
.status-pill {
display: inline-block;
padding: 2px 6px;
border-radius: 8px;
font-size: 9px;
font-weight: 600;
margin-left: 4px;
}
.status-pill--normal {
background: rgba(82, 196, 26, 0.15);
color: #4ade80;
border: 1px solid rgba(82, 196, 26, 0.3);
}
.status-pill--refunded {
background: rgba(245, 34, 45, 0.15);
color: #ff6b6b;
border: 1px solid rgba(245, 34, 45, 0.3);
}
/* 空状态 */
.empty {
text-align: center;
padding: 60px 20px;
color: rgba(255, 255, 255, 0.3);
font-size: 13px;
}
/* 底部分页 */
.pagination {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
background: rgba(26, 43, 74, 0.4);
border-top: 1px solid rgba(255, 255, 255, 0.06);
flex-shrink: 0;
}
.pagination__info {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
}
.pagination__info strong { color: #fff; }
.pagination__pages { display: flex; gap: 4px; }
.page-btn {
min-width: 28px;
padding: 4px 8px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
color: rgba(255, 255, 255, 0.7);
font-size: 11px;
cursor: pointer;
transition: all 0.15s;
font-family: Menlo, Consolas, monospace;
}
.page-btn:hover { background: rgba(74, 144, 217, 0.15); color: #fff; }
.page-btn.active {
background: #4a90d9;
border-color: #4a90d9;
color: #fff;
}
.page-btn--disabled {
opacity: 0.4;
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--warn { background: rgba(250, 173, 22, 0.92); }
.toast--success { background: rgba(82, 196, 26, 0.92); }
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" href="index.html">&#x25C0; 返回主页</a>
<span class="top-bar__title">订单列表</span>
<span class="top-bar__meta">今日 2026-08-06</span>
</div>
<!-- 主内容 -->
<div class="main-area">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="date-range">&#x1F4C5; 2026-08-06(今日)</div>
<select class="filter-select">
<option>全部餐次</option>
<option selected>午餐(当前)</option>
<option>早餐</option>
<option>晚餐</option>
</select>
<select class="filter-select">
<option>全部状态</option>
<option>正常</option>
<option>已退款</option>
</select>
<select class="filter-select">
<option>全部支付</option>
<option>在线支付</option>
<option>现金</option>
<option>餐券/补贴码</option>
<option>刷脸</option>
</select>
<div class="filter-bar__search">
<span>&#x1F50D;</span>
<input type="text" placeholder="搜索订单号 / 顾客姓名">
</div>
<div class="filter-bar__stat">
午餐单数:<strong>5</strong>
午餐营收:<strong>&#xFFE5;151.30</strong>
</div>
</div>
<!-- 订单列表 -->
<div class="order-list" id="orderList">
<!-- 表头(静态保留,不被 JS 覆盖) -->
<div class="order-head" id="orderHead">
<div>#</div>
<div>订单号 / 状态</div>
<div>餐次</div>
<div>商品</div>
<div>支付流水号</div>
<div class="order-head__amount">金额</div>
<div>支付方式</div>
<div>支付时间</div>
<div class="order-head__actions">操作</div>
</div>
<!-- 订单行容器(JS 渲染到这里) -->
<div id="orderRows"></div>
</div>
<!-- 分页 -->
<div class="pagination">
<div class="pagination__info"><strong>5</strong> 条 · 当前第 <strong>1/1</strong></div>
<div class="pagination__pages">
<button class="page-btn page-btn--disabled">&#x25C0;</button>
<button class="page-btn active">1</button>
<button class="page-btn page-btn--disabled">&#x25B6;</button>
</div>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast"></div>
<script>
/* ==================== Mock 订单数据(当前餐次:午餐) ==================== */
var mockOrders = [
{
id: 'CO-20260806-031', mealType: 'lunch', mealLabel: '午餐',
cashier: '张三',
itemCount: 5, itemsSummary: '红烧肉/清炒时蔬/鱼香肉丝/米饭/...',
payable: 41.60,
txnNo: 'WX2608061232509987',
payMethod: '在线支付', payIcon: '&#x1F4F1;',
payTime: '12:32:50',
printed: true, status: 'normal'
},
{
id: 'CO-20260806-030', mealType: 'lunch', mealLabel: '午餐',
cashier: '张三',
itemCount: 4, itemsSummary: '宫保鸡丁/番茄炒蛋/米饭/...',
payable: 32.50,
txnNo: 'FACE260806122801234',
payMethod: '刷脸支付', payIcon: '&#x1F464;',
payTime: '12:28:15',
printed: true, status: 'normal'
},
{
id: 'CO-20260806-029', mealType: 'lunch', mealLabel: '午餐',
cashier: '张三',
itemCount: 3, itemsSummary: '麻婆豆腐/番茄炒蛋/米饭',
payable: 18.50,
txnNo: 'MQ26080612180056',
payMethod: '餐券/补贴码', payIcon: '&#x1F3AB;',
payTime: '12:18:42',
printed: true, status: 'normal'
},
{
id: 'CO-20260806-028', mealType: 'lunch', mealLabel: '午餐',
cashier: '张三',
itemCount: 3, itemsSummary: '清蒸鲈鱼/蒜蓉西兰花/紫米饭',
payable: 34.00,
txnNo: 'WX2608061210304452',
payMethod: '在线支付', payIcon: '&#x1F4F1;',
payTime: '12:10:30',
printed: true, status: 'refunded'
},
{
id: 'CO-20260806-027', mealType: 'lunch', mealLabel: '午餐',
cashier: '张三',
itemCount: 4, itemsSummary: '鱼香肉丝/麻婆豆腐/米饭/...',
payable: 24.70,
txnNo: 'CASH26080612021899',
payMethod: '现金', payIcon: '&#x1F4B6;',
payTime: '12:02:18',
printed: false, status: 'normal'
}
];
function renderOrders() {
var listEl = document.getElementById('orderRows');
if (mockOrders.length === 0) {
listEl.innerHTML = '<div class="empty">&#x1F4CB; 今日暂无订单</div>';
return;
}
var html = mockOrders.map(function(o, idx) {
var mealTagClass = 'meal-tag--' + o.mealType;
var refundedClass = o.status === 'refunded' ? ' refunded' : '';
var statusPill = o.status === 'refunded'
? '<span class="status-pill status-pill--refunded">已退款</span>'
: '<span class="status-pill status-pill--normal">正常</span>';
/* 商品汇总显示:餐品 x N */
var itemsHtml = '<div class="order-row__items">&#x1F37D;&#xFE0F; 餐品 x' + o.itemCount + '</div>'
+ '<div class="order-row__items-hint">' + o.itemsSummary + '</div>';
/* 支付流水号 */
var txnHtml = '<div class="order-row__txn" title="' + o.txnNo + '">' + o.txnNo + '</div>';
/* 支付方式(独立一列) */
var payMethodHtml = '<div class="order-row__pay-method">' + o.payIcon + ' ' + o.payMethod + '</div>';
/* 支付时间(独立一列) */
var payTimeHtml = '<div class="order-row__txn">' + o.payTime + '</div>';
/* 操作按钮 - 退款按钮携带 action=refund 参数跳转详情页 */
var detailHref = '06-order-detail.html?id=' + o.id;
var refundHref = '06-order-detail.html?id=' + o.id + '&action=refund';
var actions = o.status === 'refunded'
? '<a class="action-btn" href="' + detailHref + '">详情</a>'
: '<a class="action-btn" href="' + detailHref + '">详情</a>'
+ '<a class="action-btn action-btn--gold" href="09-print-receipt.html?id=' + o.id + '">打印</a>'
+ '<a class="action-btn action-btn--danger" href="' + refundHref + '">去退款</a>';
return '<div class="order-row' + refundedClass + '" onclick="window.location.href=\'' + detailHref + '\'">'
+ '<div class="order-row__index">#' + (idx + 1) + '</div>'
+ '<div>'
+ '<div class="order-row__id">' + o.id + statusPill + '</div>'
+ '</div>'
+ '<div><span class="meal-tag ' + mealTagClass + '">' + o.mealLabel + '</span></div>'
+ '<div>' + itemsHtml + '</div>'
+ '<div>' + txnHtml + '</div>'
+ '<div class="order-row__amount">&#xFFE5;' + o.payable.toFixed(2) + '</div>'
+ '<div>' + payMethodHtml + '</div>'
+ '<div>' + payTimeHtml + '</div>'
+ '<div class="order-row__actions" onclick="event.stopPropagation();">' + actions + '</div>'
+ '</div>';
}).join('');
listEl.innerHTML = html;
}
function showToast(msg, type) {
var el = document.getElementById('toast');
el.textContent = msg;
el.className = 'toast';
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'); }, 2200);
}
renderOrders();
</script>
</body>
</html>
@@ -0,0 +1,999 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: #0e1326;
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.top-bar {
display: flex;
align-items: center;
height: 44px;
background: #1a2b4a;
padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
cursor: pointer;
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__meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
/* 主内容:左右两列 */
.main-area {
flex: 1;
display: grid;
grid-template-columns: 1fr 360px;
overflow: hidden;
}
/* ============ 左列:订单信息 + 商品明细 ============ */
.left-col {
display: flex;
flex-direction: column;
overflow-y: auto;
padding: 18px 20px;
gap: 14px;
scrollbar-width: none;
}
.left-col::-webkit-scrollbar { display: none; }
.card {
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 10px;
padding: 14px 16px;
}
.card__title {
font-size: 12px;
color: rgba(255, 255, 255, 0.55);
letter-spacing: 1px;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.card__title::before {
content: "";
width: 3px;
height: 12px;
background: #4a90d9;
border-radius: 2px;
}
/* 订单头 */
.order-head {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 12px;
border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
}
.order-head__id {
font-size: 18px;
color: #fff;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
}
.order-head__status {
display: flex;
gap: 6px;
}
.status-pill {
display: inline-block;
padding: 4px 10px;
border-radius: 12px;
font-size: 11px;
font-weight: 600;
}
.status-pill--normal {
background: rgba(82, 196, 26, 0.15);
color: #4ade80;
border: 1px solid rgba(82, 196, 26, 0.3);
}
.status-pill--printed {
background: rgba(74, 144, 217, 0.15);
color: #60a5fa;
border: 1px solid rgba(74, 144, 217, 0.3);
}
.status-pill--refunded {
background: rgba(245, 34, 45, 0.15);
color: #ff6b6b;
border: 1px solid rgba(245, 34, 45, 0.3);
}
/* 信息网格 */
.info-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 12px;
}
.info-item__label {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
margin-bottom: 4px;
}
.info-item__value {
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
}
.meal-tag {
display: inline-block;
font-size: 10px;
line-height: 1;
padding: 4px 8px;
border-radius: 9px;
font-weight: 600;
}
.meal-tag--lunch {
background: rgba(37, 99, 235, 0.18);
color: #60a5fa;
border: 1px solid rgba(37, 99, 235, 0.35);
}
/* 商品明细表 */
.item-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.item-table th {
text-align: left;
padding: 8px 6px;
color: rgba(255, 255, 255, 0.5);
font-weight: 600;
font-size: 11px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.item-table th.num { text-align: right; }
.item-table td {
padding: 8px 6px;
color: rgba(255, 255, 255, 0.85);
border-bottom: 1px dashed rgba(255, 255, 255, 0.05);
}
.item-table td.num { text-align: right; font-family: Menlo, Consolas, monospace; }
.item-table tr.zone-header td {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
padding-top: 10px;
font-weight: 600;
letter-spacing: 0.5px;
border-bottom: none;
}
.item-table .item-name {
display: flex;
align-items: center;
gap: 8px;
}
.item-name__thumb {
width: 26px;
height: 26px;
border-radius: 6px;
background: linear-gradient(135deg, rgba(74, 144, 217, 0.2), rgba(10, 196, 168, 0.2));
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.item-table .subtotal {
color: #0AC4A8;
font-weight: 700;
}
/* 金额汇总 */
.amount-list { display: flex; flex-direction: column; gap: 6px; }
.amount-line {
display: flex;
justify-content: space-between;
font-size: 13px;
}
.amount-line__label { color: rgba(255, 255, 255, 0.6); }
.amount-line__value { color: rgba(255, 255, 255, 0.9); font-weight: 600; }
.amount-line--total {
padding-top: 10px;
margin-top: 4px;
border-top: 1px dashed rgba(255, 255, 255, 0.1);
}
.amount-line--total .amount-line__label { font-size: 14px; color: #fff; }
.amount-line--total .amount-line__value {
font-size: 22px;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
}
/* 退款金额显示 */
.refund-summary {
display: none;
padding: 10px 12px;
background: rgba(245, 34, 45, 0.1);
border: 1px solid rgba(245, 34, 45, 0.3);
border-radius: 8px;
font-size: 13px;
color: #ff6b6b;
justify-content: space-between;
}
.refund-summary.show { display: flex; }
.refund-summary__amount {
font-weight: 700;
font-family: Menlo, Consolas, monospace;
}
/* ============ 右列:操作面板 ============ */
.right-col {
display: flex;
flex-direction: column;
padding: 18px 20px;
background: rgba(26, 43, 74, 0.2);
border-left: 1px solid rgba(255, 255, 255, 0.06);
gap: 12px;
overflow-y: auto;
scrollbar-width: none;
}
.right-col::-webkit-scrollbar { display: none; }
/* 操作按钮组 */
.btn-group { display: flex; flex-direction: column; gap: 8px; }
.btn {
padding: 12px;
border: none;
border-radius: 8px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
font-family: inherit;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
text-decoration: none;
}
.btn--ghost {
background: rgba(255, 255, 255, 0.05);
color: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.btn--ghost:hover {
background: rgba(74, 144, 217, 0.1);
border-color: rgba(74, 144, 217, 0.35);
}
.btn--gold {
background: rgba(251, 191, 36, 0.15);
color: #fbbf24;
border: 1px solid rgba(251, 191, 36, 0.35);
}
.btn--gold:hover {
background: rgba(251, 191, 36, 0.25);
}
.btn--danger {
background: rgba(245, 34, 45, 0.12);
color: #ff6b6b;
border: 1px solid rgba(245, 34, 45, 0.35);
}
.btn--danger:hover {
background: rgba(245, 34, 45, 0.22);
}
/* 退款流程弹层 */
.refund-panel {
display: none;
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(245, 34, 45, 0.3);
border-radius: 10px;
padding: 14px;
flex-direction: column;
gap: 10px;
}
.refund-panel.show { display: flex; }
.refund-panel__title {
font-size: 13px;
color: #ff6b6b;
font-weight: 600;
display: flex;
align-items: center;
gap: 6px;
}
.refund-panel__label {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
}
.refund-reason {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
}
.refund-reason__item {
padding: 8px 6px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 6px;
font-size: 11px;
color: rgba(255, 255, 255, 0.75);
cursor: pointer;
transition: all 0.15s;
text-align: center;
}
.refund-reason__item:hover {
background: rgba(245, 34, 45, 0.1);
border-color: rgba(245, 34, 45, 0.35);
color: #fff;
}
.refund-reason__item.active {
background: rgba(245, 34, 45, 0.15);
border-color: #f5222d;
color: #fff;
}
.refund-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-top: 4px;
}
/* 退款方式切换(全额/部分) */
.refund-type {
display: flex;
flex-direction: column;
gap: 6px;
}
.refund-type__item {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 12px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 8px;
cursor: pointer;
transition: all 0.15s;
}
.refund-type__item:hover {
background: rgba(245, 34, 45, 0.06);
border-color: rgba(245, 34, 45, 0.25);
}
.refund-type__item.active {
background: rgba(245, 34, 45, 0.1);
border-color: #f5222d;
}
.refund-type__radio {
width: 16px;
height: 16px;
border-radius: 50%;
border: 2px solid rgba(255, 255, 255, 0.3);
flex-shrink: 0;
margin-top: 2px;
position: relative;
transition: all 0.15s;
}
.refund-type__item.active .refund-type__radio {
border-color: #f5222d;
}
.refund-type__item.active .refund-type__radio::after {
content: "";
position: absolute;
top: 3px;
left: 3px;
width: 8px;
height: 8px;
border-radius: 50%;
background: #f5222d;
}
.refund-type__body { flex: 1; }
.refund-type__name {
font-size: 13px;
color: #fff;
font-weight: 600;
margin-bottom: 2px;
}
.refund-type__hint {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
}
/* 部分退款金额输入 */
.refund-amount-wrap {
display: none;
}
.refund-amount-wrap.show { display: block; }
.refund-amount-input {
display: flex;
align-items: center;
gap: 4px;
padding: 8px 12px;
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(245, 34, 45, 0.3);
border-radius: 8px;
}
.refund-amount-input__symbol {
font-size: 18px;
color: #ff6b6b;
font-weight: 700;
}
.refund-amount-input input {
flex: 1;
background: none;
border: none;
color: #fff;
font-size: 18px;
font-family: Menlo, Consolas, monospace;
outline: none;
text-align: right;
}
.refund-amount-quick {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 4px;
margin-top: 6px;
}
.refund-amount-quick button {
padding: 6px 0;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
color: rgba(255, 255, 255, 0.85);
font-size: 11px;
cursor: pointer;
transition: all 0.15s;
font-family: Menlo, Consolas, monospace;
}
.refund-amount-quick button:hover {
background: rgba(245, 34, 45, 0.15);
border-color: rgba(245, 34, 45, 0.35);
color: #fff;
}
/* 退款备注 */
.refund-note {
width: 100%;
padding: 8px 10px;
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
color: #fff;
font-size: 12px;
font-family: inherit;
resize: vertical;
outline: none;
line-height: 1.6;
}
.refund-note:focus { border-color: #f5222d; }
.refund-note::placeholder { color: rgba(255, 255, 255, 0.35); }
.refund-note__counter {
text-align: right;
font-size: 10px;
color: rgba(255, 255, 255, 0.4);
margin-top: 2px;
}
/* 让 summary 始终展示 */
.refund-panel .refund-summary { display: flex !important; }
/* 退款记录(已退款订单显示) */
.refund-record {
display: none;
padding: 12px;
background: rgba(245, 34, 45, 0.08);
border: 1px solid rgba(245, 34, 45, 0.25);
border-radius: 8px;
font-size: 12px;
color: rgba(255, 255, 255, 0.75);
line-height: 1.7;
}
.refund-record.show { display: block; }
.refund-record strong { color: #ff6b6b; }
/* 关联信息 */
.related-info {
padding: 10px 12px;
background: rgba(26, 43, 74, 0.5);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 8px;
font-size: 11px;
color: rgba(255, 255, 255, 0.6);
line-height: 1.7;
}
.related-info__row {
display: flex;
justify-content: space-between;
}
.related-info__row strong { color: rgba(255, 255, 255, 0.85); }
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" href="05-orders.html">&#x25C0; 返回订单列表</a>
<span class="top-bar__title">订单详情</span>
<span class="top-bar__meta">2026-08-06</span>
</div>
<!-- 主内容 -->
<div class="main-area">
<!-- 左列:订单信息 -->
<div class="left-col">
<!-- 订单头 -->
<div class="card">
<div class="order-head">
<div>
<div class="order-head__id">CO-20260806-031</div>
<div style="font-size:11px;color:rgba(255,255,255,0.4);margin-top:4px;">
下单:2026-08-06 12:15:30 · 支付:12:32:50
</div>
</div>
<div class="order-head__status">
<span class="status-pill status-pill--normal">正常</span>
<span class="status-pill status-pill--printed">已打印</span>
</div>
</div>
<div class="info-grid" style="margin-top:14px;">
<div class="info-item">
<div class="info-item__label">餐次</div>
<div class="info-item__value"><span class="meal-tag meal-tag--lunch">午餐</span></div>
</div>
<div class="info-item">
<div class="info-item__label">餐线</div>
<div class="info-item__value">一楼 A 区 2 号</div>
</div>
<div class="info-item">
<div class="info-item__label">收银员</div>
<div class="info-item__value">张三 (CS001)</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">5 件</div>
</div>
<div class="info-item">
<div class="info-item__label">订单总重</div>
<div class="info-item__value">1040g</div>
</div>
</div>
</div>
<!-- 商品明细 -->
<div class="card">
<div class="card__title">商品明细</div>
<table class="item-table">
<thead>
<tr>
<th>餐品</th>
<th class="num">单价/100g</th>
<th class="num">取用量</th>
<th class="num">小计</th>
</tr>
</thead>
<tbody>
<tr class="zone-header"><td colspan="4">【档口】 ×3</td></tr>
<tr>
<td><div class="item-name"><span class="item-name__thumb">&#x1F356;</span>红烧肉</div></td>
<td class="num">&#xFFE5;12.00</td>
<td class="num">180g</td>
<td class="num subtotal">21.60</td>
</tr>
<tr>
<td><div class="item-name"><span class="item-name__thumb">&#x1F35F;</span>鱼香肉丝</div></td>
<td class="num">&#xFFE5;7.50</td>
<td class="num">160g</td>
<td class="num subtotal">12.00</td>
</tr>
<tr>
<td><div class="item-name"><span class="item-name__thumb">&#x1F372;</span>冬瓜排骨汤</div></td>
<td class="num">&#xFFE5;1.00</td>
<td class="num">300g</td>
<td class="num subtotal">3.00</td>
</tr>
<tr class="zone-header"><td colspan="4">【餐线】 ×2</td></tr>
<tr>
<td><div class="item-name"><span class="item-name__thumb">&#x1F966;</span>清炒时蔬</div></td>
<td class="num">&#xFFE5;4.00</td>
<td class="num">150g</td>
<td class="num subtotal">6.00</td>
</tr>
<tr>
<td><div class="item-name"><span class="item-name__thumb">&#x1F35A;</span>米饭</div></td>
<td class="num">&#xFFE5;1.60</td>
<td class="num">250g</td>
<td class="num subtotal">4.00</td>
</tr>
</tbody>
</table>
</div>
<!-- 金额汇总 -->
<div class="card">
<div class="card__title">金额汇总</div>
<div class="amount-list">
<div class="amount-line">
<span class="amount-line__label">商品合计</span>
<span class="amount-line__value">&#xFFE5;46.60</span>
</div>
<div class="amount-line">
<span class="amount-line__label">企业补贴优惠</span>
<span class="amount-line__value" style="color:#4ade80;">-&#xFFE5;5.00</span>
</div>
<div class="amount-line amount-line--total">
<span class="amount-line__label">实付金额</span>
<span class="amount-line__value">&#xFFE5;41.60</span>
</div>
</div>
<div style="margin-top:14px;padding-top:12px;border-top:1px dashed rgba(255,255,255,0.1);">
<div class="amount-line">
<span class="amount-line__label">支付方式</span>
<span class="amount-line__value">&#x1F4F1; 在线支付 · 微信支付</span>
</div>
<div class="amount-line" style="margin-top:6px;">
<span class="amount-line__label">交易流水号</span>
<span class="amount-line__value" style="font-family:Menlo,monospace;font-size:11px;">WX2026080612305012</span>
</div>
</div>
</div>
</div>
<!-- 右列:操作面板 -->
<div class="right-col">
<!-- 退款记录(已退款时显示) -->
<div class="refund-record" id="refundRecord" style="display:none;">
<div style="margin-bottom:6px;color:#ff6b6b;font-weight:600;">&#x26A0;&#xFE0F; 已退款</div>
<div>退款金额:<strong>&#xFFE5;41.60</strong></div>
<div>退款方式:原路退回(微信)</div>
<div>退款时间:2026-08-06 13:05:12</div>
<div>操作人:张三 (CS001)</div>
<div>退款原因:顾客反馈菜品口味问题</div>
</div>
<!-- 正常订单操作 -->
<div id="normalActions">
<div class="card__title" style="font-size:12px;color:rgba(255,255,255,0.55);letter-spacing:1px;margin-bottom:10px;">订单操作</div>
<div class="btn-group">
<button class="btn btn--gold" onclick="window.location.href='09-print-receipt.html'">
&#x1F5A8;&#xFE0F; 重新打印小票
</button>
<button class="btn btn--ghost" onclick="alert('已发起补齐明细流程')">
&#x270F;&#xFE0F; 补齐明细(漏记/多记)
</button>
<button class="btn btn--ghost" onclick="alert('订单已加入今日异常单列表')">
&#x26A0;&#xFE0F; 标记为异常订单
</button>
<button class="btn btn--danger" onclick="toggleRefundPanel()">
&#x1F4B8; 申请退款
</button>
</div>
<!-- 退款流程面板 -->
<div class="refund-panel" id="refundPanel" style="margin-top:12px;">
<div class="refund-panel__title">&#x1F4B8; 发起退款</div>
<!-- 退款方式切换 -->
<div class="refund-panel__label">退款方式</div>
<div class="refund-type">
<div class="refund-type__item active" data-type="full" onclick="switchRefundType('full')">
<div class="refund-type__radio"></div>
<div class="refund-type__body">
<div class="refund-type__name">全额退款</div>
<div class="refund-type__hint">一键退回 &#xFFE5;41.60 到原支付账户</div>
</div>
</div>
<div class="refund-type__item" data-type="partial" onclick="switchRefundType('partial')">
<div class="refund-type__radio"></div>
<div class="refund-type__body">
<div class="refund-type__name">部分退款</div>
<div class="refund-type__hint">手动输入退款金额(最多 &#xFFE5;41.60)</div>
</div>
</div>
</div>
<!-- 部分退款金额输入 -->
<div class="refund-amount-wrap" id="partialAmountWrap">
<div class="refund-panel__label" style="margin-top:4px;">退款金额</div>
<div class="refund-amount-input">
<span class="refund-amount-input__symbol">&#xFFE5;</span>
<input type="number" id="partialAmount" value="0.00" step="0.01" min="0" max="41.60" oninput="updatePartialAmount()">
</div>
<div class="refund-amount-quick">
<button onclick="setPartial(10)">10</button>
<button onclick="setPartial(20)">20</button>
<button onclick="setPartial(41.60)">全额</button>
<button onclick="setPartial(0)">清零</button>
</div>
</div>
<!-- 退款原因 -->
<div class="refund-panel__label" style="margin-top:4px;">退款原因(必选)</div>
<div class="refund-reason" id="refundReason">
<div class="refund-reason__item" onclick="selectReason(this)">顾客反馈</div>
<div class="refund-reason__item" onclick="selectReason(this)">操作错误</div>
<div class="refund-reason__item" onclick="selectReason(this)">商品问题</div>
<div class="refund-reason__item" onclick="selectReason(this)">重复结算</div>
</div>
<!-- 退款备注 -->
<div class="refund-panel__label" style="margin-top:4px;">退款备注(可选)</div>
<textarea class="refund-note" id="refundNote" placeholder="补充说明本次退款的具体原因,如:顾客反馈米饭夹生,已重新补一份..." rows="3" maxlength="200" oninput="updateNoteCounter()"></textarea>
<div class="refund-note__counter"><span id="noteCounter">0</span>/200</div>
<!-- 退款金额汇总 -->
<div class="refund-summary">
<span>本次退款金额</span>
<span class="refund-summary__amount" id="refundAmountDisplay">&#xFFE5;41.60</span>
</div>
<div class="refund-actions">
<button class="btn btn--ghost" onclick="toggleRefundPanel()">取消</button>
<button class="btn btn--danger" onclick="confirmRefund()">确认退款</button>
</div>
</div>
</div>
<!-- 关联信息 -->
<div style="margin-top:auto;">
<div class="related-info">
<div class="related-info__row">
<span>原价</span>
<strong>&#xFFE5;46.60</strong>
</div>
<div class="related-info__row">
<span>优惠</span>
<strong>-&#xFFE5;5.00</strong>
</div>
<div class="related-info__row">
<span>件数</span>
<strong>5 件 / 1040g</strong>
</div>
<div class="related-info__row" style="margin-top:6px;padding-top:6px;border-top:1px dashed rgba(255,255,255,0.1);">
<span>餐次</span>
<strong>午餐 · 一楼 A 区</strong>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast"></div>
<style>
.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--warn { background: rgba(250, 173, 22, 0.92); }
.toast--success { background: rgba(82, 196, 26, 0.92); }
</style>
<script>
/* 订单原金额 */
var ORDER_PAYABLE = 41.60;
/* 当前退款方式:full / partial */
var currentRefundType = 'full';
function toggleRefundPanel() {
var panel = document.getElementById('refundPanel');
panel.classList.toggle('show');
/* 默认重置为全额退款 */
if (panel.classList.contains('show')) {
switchRefundType('full');
}
}
/* 切换退款方式 */
function switchRefundType(type) {
currentRefundType = type;
document.querySelectorAll('.refund-type__item').forEach(function(el) {
el.classList.toggle('active', el.dataset.type === type);
});
var wrap = document.getElementById('partialAmountWrap');
wrap.classList.toggle('show', type === 'partial');
updateRefundDisplay();
}
/* 部分退款:快捷金额 */
function setPartial(v) {
document.getElementById('partialAmount').value = v.toFixed(2);
updatePartialAmount();
}
function updatePartialAmount() {
var input = document.getElementById('partialAmount');
var v = parseFloat(input.value) || 0;
/* 不超过订单应付 */
if (v > ORDER_PAYABLE) {
v = ORDER_PAYABLE;
input.value = v.toFixed(2);
showToast('退款金额不能超过应付金额 ¥' + ORDER_PAYABLE.toFixed(2), 'warn');
}
if (v < 0) {
v = 0;
input.value = '0.00';
}
updateRefundDisplay();
}
/* 更新退款金额显示 */
function updateRefundDisplay() {
var amount = currentRefundType === 'full' ? ORDER_PAYABLE : (parseFloat(document.getElementById('partialAmount').value) || 0);
document.getElementById('refundAmountDisplay').innerHTML = '&#xFFE5;' + amount.toFixed(2);
}
/* 退款原因选择 */
function selectReason(el) {
document.querySelectorAll('.refund-reason__item').forEach(function(e) {
e.classList.remove('active');
});
el.classList.add('active');
}
/* 备注字数计数 */
function updateNoteCounter() {
var len = document.getElementById('refundNote').value.length;
document.getElementById('noteCounter').textContent = len;
}
/* 确认退款 */
function confirmRefund() {
var reasonEl = document.querySelector('.refund-reason__item.active');
if (!reasonEl) {
showToast('请选择退款原因', 'warn');
return;
}
var reason = reasonEl.textContent.trim();
var note = document.getElementById('refundNote').value.trim();
var amount = currentRefundType === 'full' ? ORDER_PAYABLE : (parseFloat(document.getElementById('partialAmount').value) || 0);
if (amount <= 0) {
showToast('退款金额必须大于 0', 'warn');
return;
}
if (amount > ORDER_PAYABLE) {
showToast('退款金额不能超过应付金额', 'warn');
return;
}
var typeText = currentRefundType === 'full' ? '全额退款' : '部分退款';
var msg = '确认' + typeText + '?\n\n'
+ '退款金额:¥' + amount.toFixed(2) + '\n'
+ '退款原因:' + reason + '\n'
+ (note ? '备注:' + note + '\n' : '')
+ '此操作不可撤销。';
if (confirm(msg)) {
showToast(typeText + ' ¥' + amount.toFixed(2) + ' 已发起', 'success');
/* 隐藏操作面板,显示退款记录 */
setTimeout(function() {
document.getElementById('normalActions').style.display = 'none';
var record = document.getElementById('refundRecord');
record.style.display = 'block';
/* 渲染退款记录内容 */
record.innerHTML =
'<div style="margin-bottom:6px;color:#ff6b6b;font-weight:600;">&#x26A0;&#xFE0F; ' + typeText + '已发起</div>'
+ '<div>退款金额:<strong>¥' + amount.toFixed(2) + '</strong> / ' + (currentRefundType === 'full' ? '原订单全额' : ('剩余 ¥' + (ORDER_PAYABLE - amount).toFixed(2) + ' 已结算')) + '</div>'
+ '<div>退款方式:原路退回(微信)</div>'
+ '<div>退款时间:2026-08-06 14:30:25</div>'
+ '<div>操作人:张三 (CS001)</div>'
+ '<div>退款原因:' + reason + '</div>'
+ (note ? '<div>备注:' + note + '</div>' : '');
}, 1200);
}
}
function showToast(msg, type) {
var el = document.getElementById('toast');
el.textContent = msg;
el.className = 'toast';
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'); }, 2200);
}
/* ==================== URL 参数解析 ====================
* 从订单列表跳转时携带的参数:
* - id:订单号(用于显示)
* - action=refund:自动展开退款面板
* 例如:06-order-detail.html?id=CO-20260806-031&action=refund
*/
function getQueryParam(name) {
var match = (window.location.search.match(new RegExp('[?&]' + name + '=([^&]+)')) || [])[1];
return match ? decodeURIComponent(match) : null;
}
(function autoInitFromUrl() {
/* 同步订单号(若 URL 带了 id 参数,显示在订单头) */
var orderId = getQueryParam('id');
if (orderId) {
var idEl = document.querySelector('.order-head__id');
if (idEl) idEl.textContent = orderId;
}
var action = getQueryParam('action');
/* 退款操作:自动展开退款面板并滚动到右侧 */
if (action === 'refund') {
/* 等待 DOM 渲染完成后展开 */
setTimeout(function() {
toggleRefundPanel();
/* 滚动右侧操作区到退款面板位置 */
var panel = document.getElementById('refundPanel');
var rightCol = panel.closest('.right-col');
if (rightCol && panel) {
rightCol.scrollTop = panel.offsetTop - 20;
}
/* 高亮提示一下退款面板 */
panel.style.boxShadow = '0 0 0 3px rgba(245, 34, 45, 0.3)';
setTimeout(function() { panel.style.boxShadow = ''; }, 1800);
showToast('请在下方填写退款信息', 'warn');
}, 200);
}
})();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,888 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: #0e1326;
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.top-bar {
display: flex;
align-items: center;
height: 44px;
background: #1a2b4a;
padding: 0 20px;
flex-shrink: 0;
}
.back-btn {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
cursor: pointer;
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__meta {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
/* 主内容 */
.main-area {
flex: 1;
display: grid;
grid-template-columns: 1fr 360px;
overflow: hidden;
}
/* ============ 左列:商品操作区 ============ */
.items-col {
display: flex;
flex-direction: column;
overflow: hidden;
}
.items-col__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 20px;
background: rgba(26, 43, 74, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.items-col__title {
font-size: 13px;
color: rgba(255, 255, 255, 0.85);
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.items-col__icon {
padding: 2px 8px;
background: rgba(251, 191, 36, 0.15);
color: #fbbf24;
border: 1px solid rgba(251, 191, 36, 0.3);
border-radius: 9px;
font-size: 11px;
font-weight: 600;
}
.items-col__hint {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
}
/* Tab 切换:当前商品 / 添加商品 */
.tabs {
display: flex;
gap: 6px;
padding: 10px 20px;
background: rgba(26, 43, 74, 0.3);
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.tab {
padding: 7px 16px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 6px;
color: rgba(255, 255, 255, 0.65);
font-size: 12px;
cursor: pointer;
transition: all 0.15s;
}
.tab.active {
background: rgba(74, 144, 217, 0.15);
border-color: #4a90d9;
color: #fff;
font-weight: 600;
}
/* 商品列表区 */
.items-list {
flex: 1;
overflow-y: auto;
padding: 12px 16px;
scrollbar-width: none;
}
.items-list::-webkit-scrollbar { display: none; }
.zone-group { margin-bottom: 14px; }
/* 表头(对齐 03-checkout) */
.table-head {
display: grid;
grid-template-columns: 24px auto 1fr auto 32px;
gap: 10px;
padding: 6px 14px;
font-size: 11px;
color: rgba(255, 255, 255, 0.4);
letter-spacing: 1px;
font-weight: 500;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
margin-bottom: 4px;
}
.table-head__name { text-align: left; }
.table-head__weight { text-align: center; justify-self: center; }
.table-head__price { text-align: right; }
/* 分组标题(对齐 03-checkout) */
.zone-header {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
font-weight: 600;
letter-spacing: 0.5px;
padding: 6px 0 8px;
border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
margin-bottom: 6px;
margin-top: 8px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.zone-header__name {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
font-weight: 600;
letter-spacing: 0.5px;
display: flex;
align-items: center;
gap: 6px;
}
.zone-header__count {
padding: 1px 8px;
background: rgba(74, 144, 217, 0.18);
border-radius: 10px;
font-size: 11px;
color: #60a5fa;
font-weight: 500;
margin-left: 6px;
}
.zone-header__total {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
}
/* 商品行(对齐 03-checkout item-card 样式) */
.item-card {
display: grid;
grid-template-columns: 24px auto 1fr auto 28px;
gap: 10px;
padding: 8px 14px;
background: rgba(26, 43, 74, 0.35);
border: 1px solid rgba(255, 255, 255, 0.04);
border-radius: 8px;
margin-bottom: 4px;
align-items: center;
}
.item-card.added {
background: rgba(82, 196, 26, 0.08);
border-color: rgba(82, 196, 26, 0.3);
}
.item-card.removed {
opacity: 0.45;
background: rgba(245, 34, 45, 0.05);
border-color: rgba(245, 34, 45, 0.25);
}
.item-card.removed .item-card__name { text-decoration: line-through; }
.item-card__seq {
width: 22px;
height: 22px;
border-radius: 50%;
background: rgba(74, 144, 217, 0.18);
border: 1px solid rgba(74, 144, 217, 0.35);
color: #60a5fa;
font-size: 11px;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.item-card__info {
display: flex;
align-items: baseline;
gap: 8px;
min-width: 0;
}
.item-card__name {
font-size: 15px;
color: #fff;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-card__unit-price {
font-size: 12px;
color: rgba(255, 255, 255, 0.55);
font-family: Menlo, Consolas, monospace;
flex-shrink: 0;
}
.item-card__weight {
font-size: 12px;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
padding: 2px 10px;
background: rgba(10, 196, 168, 0.12);
border-radius: 10px;
white-space: nowrap;
text-align: center;
min-width: 76px;
justify-self: center;
}
.item-card.removed .item-card__weight {
color: #ff6b6b;
background: rgba(245, 34, 45, 0.1);
}
.item-card.added .item-card__weight {
color: #4ade80;
background: rgba(82, 196, 26, 0.12);
}
.item-card__price {
font-size: 16px;
color: #0AC4A8;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
white-space: nowrap;
}
.item-card__action {
width: 28px;
height: 28px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.15s;
font-size: 13px;
border: 1px solid;
flex-shrink: 0;
}
.item-card__action--remove {
background: rgba(245, 34, 45, 0.12);
border-color: rgba(245, 34, 45, 0.35);
color: #ff6b6b;
}
.item-card__action--remove:hover { background: rgba(245, 34, 45, 0.25); }
.item-card__action--restore {
background: rgba(82, 196, 26, 0.12);
border-color: rgba(82, 196, 26, 0.35);
color: #4ade80;
}
.item-card__action--restore:hover { background: rgba(82, 196, 26, 0.25); }
/* 变更标记 */
.change-badge {
display: inline-block;
padding: 2px 6px;
border-radius: 8px;
font-size: 9px;
font-weight: 700;
margin-left: 6px;
}
.change-badge--add {
background: rgba(82, 196, 26, 0.15);
color: #4ade80;
}
.change-badge--remove {
background: rgba(245, 34, 45, 0.15);
color: #ff6b6b;
}
/* 添加商品候选区 */
.candidate-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
}
.candidate-item {
padding: 10px;
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 8px;
cursor: pointer;
transition: all 0.15s;
display: flex;
flex-direction: column;
gap: 4px;
text-align: center;
}
.candidate-item:hover {
background: rgba(82, 196, 26, 0.08);
border-color: rgba(82, 196, 26, 0.3);
transform: translateY(-1px);
}
.candidate-item__thumb {
font-size: 24px;
}
.candidate-item__name {
font-size: 12px;
color: #fff;
font-weight: 600;
}
.candidate-item__meta {
font-size: 10px;
color: rgba(255, 255, 255, 0.55);
}
.candidate-item__add {
margin-top: 4px;
padding: 4px;
background: rgba(82, 196, 26, 0.15);
border: 1px solid rgba(82, 196, 26, 0.3);
border-radius: 4px;
color: #4ade80;
font-size: 11px;
font-weight: 600;
}
/* 搜索栏 */
.search-bar {
padding: 0 4px 12px;
}
.search-input {
width: 100%;
padding: 8px 12px;
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
color: #fff;
font-size: 12px;
outline: none;
font-family: inherit;
}
.search-input:focus { border-color: #4a90d9; }
/* ============ 右列:差额汇总 ============ */
.summary-col {
display: flex;
flex-direction: column;
padding: 18px 20px;
background: rgba(26, 43, 74, 0.2);
border-left: 1px solid rgba(255, 255, 255, 0.06);
gap: 14px;
overflow-y: auto;
scrollbar-width: none;
}
.summary-col::-webkit-scrollbar { display: none; }
.section-label {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
letter-spacing: 1px;
display: flex;
align-items: center;
gap: 6px;
}
.section-label::before {
content: "";
width: 3px;
height: 11px;
background: #fbbf24;
border-radius: 2px;
}
/* 变更前后对比 */
.compare-block {
background: rgba(26, 43, 74, 0.4);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 10px;
padding: 14px;
}
.compare-row {
display: flex;
justify-content: space-between;
padding: 6px 0;
font-size: 12px;
}
.compare-row + .compare-row { border-top: 1px dashed rgba(255, 255, 255, 0.06); }
.compare-row__label { color: rgba(255, 255, 255, 0.6); }
.compare-row__value { color: rgba(255, 255, 255, 0.9); font-weight: 600; }
.compare-row--old .compare-row__value {
color: rgba(255, 255, 255, 0.55);
text-decoration: line-through;
}
.compare-row--new .compare-row__value { color: #fff; }
.compare-row--delta .compare-row__value {
color: #4ade80;
font-size: 16px;
font-family: Menlo, Consolas, monospace;
}
.compare-row--delta-minus .compare-row__value { color: #ff6b6b; }
/* 变更日志 */
.change-log {
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 8px;
padding: 10px 12px;
max-height: 180px;
overflow-y: auto;
scrollbar-width: none;
font-size: 12px;
}
.change-log::-webkit-scrollbar { display: none; }
.change-log__empty {
text-align: center;
color: rgba(255, 255, 255, 0.3);
padding: 20px 0;
}
.log-item {
display: flex;
gap: 6px;
padding: 5px 0;
line-height: 1.5;
}
.log-item + .log-item { border-top: 1px dashed rgba(255, 255, 255, 0.05); }
.log-item__icon { font-size: 12px; }
.log-item__text { flex: 1; color: rgba(255, 255, 255, 0.75); }
.log-item__name { color: #fff; font-weight: 600; }
.log-item__amount { font-family: Menlo, Consolas, monospace; }
.log-item__amount--add { color: #4ade80; }
.log-item__amount--remove { color: #ff6b6b; }
.log-item__time {
font-size: 10px;
color: rgba(255, 255, 255, 0.35);
font-family: Menlo, Consolas, monospace;
}
/* 操作按钮 */
.actions {
margin-top: auto;
display: grid;
grid-template-columns: 1fr 2fr;
gap: 8px;
}
.btn {
padding: 13px 12px;
border: none;
border-radius: 8px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
font-family: inherit;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
}
.btn--ghost {
background: rgba(255, 255, 255, 0.05);
color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(255, 255, 255, 0.12);
}
.btn--ghost:hover {
background: rgba(245, 34, 45, 0.12);
border-color: rgba(245, 34, 45, 0.35);
color: #ff6b6b;
}
.btn--primary {
background: linear-gradient(135deg, #fbbf24, #fb923c);
color: #fff;
box-shadow: 0 6px 20px rgba(251, 191, 36, 0.35);
}
.btn--primary:hover { transform: translateY(-1px); }
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" href="03-checkout.html">&#x25C0; 返回结算</a>
<span class="top-bar__title">补齐明细</span>
<span class="top-bar__meta">订单 CO-20260806-031</span>
</div>
<!-- 主内容 -->
<div class="main-area">
<!-- 左列:商品操作 -->
<div class="items-col">
<div class="items-col__header">
<div class="items-col__title">
&#x270F;&#xFE0F; 修正明细
<span class="items-col__icon">支付前修正</span>
</div>
<div class="items-col__hint">点击 - 移除多记商品,在添加候选区点 + 补齐漏记</div>
</div>
<div class="tabs">
<div class="tab active" onclick="switchTab('current')">当前订单(5)</div>
<div class="tab" onclick="switchTab('add')">添加商品</div>
</div>
<!-- 当前订单商品 -->
<div class="items-list" id="currentList"></div>
<!-- 添加商品候选区(默认隐藏) -->
<div class="items-list" id="addList" style="display:none;">
<div class="search-bar">
<input type="text" class="search-input" placeholder="&#x1F50D; 搜索菜品名称..." id="searchInput" oninput="filterCandidates()">
</div>
<div class="zone-group">
<div class="zone-header">
<span class="zone-header__name">&#x1F95C; 营养秤 · 餐线菜品</span>
<span class="zone-header__total">8 个候选</span>
</div>
<div class="candidate-grid" id="candidateScale"></div>
</div>
<div class="zone-group">
<div class="zone-header">
<span class="zone-header__name">&#x2696;&#xFE0F; 档口秤 · 档口菜品</span>
<span class="zone-header__total">6 个候选</span>
</div>
<div class="candidate-grid" id="candidateStall"></div>
</div>
</div>
</div>
<!-- 右列:差额汇总 -->
<div class="summary-col">
<div>
<div class="section-label">金额变化对比</div>
<div class="compare-block" style="margin-top:8px;">
<div class="compare-row compare-row--old">
<span class="compare-row__label">原订单合计</span>
<span class="compare-row__value">&#xFFE5;46.60</span>
</div>
<div class="compare-row">
<span class="compare-row__label">本次修正</span>
<span class="compare-row__value" id="changeAmount">+&#xFFE5;0.00</span>
</div>
<div class="compare-row compare-row--new">
<span class="compare-row__label">修正后合计</span>
<span class="compare-row__value" id="newAmount">&#xFFE5;46.60</span>
</div>
<div class="compare-row" style="border-top:1px solid rgba(255,255,255,0.1);margin-top:6px;padding-top:10px;">
<span class="compare-row__label">企业补贴优惠</span>
<span class="compare-row__value" style="color:#4ade80;">-&#xFFE5;5.00</span>
</div>
<div class="compare-row compare-row--delta" id="deltaRow">
<span class="compare-row__label">应付金额</span>
<span class="compare-row__value" id="newPayable">&#xFFE5;41.60</span>
</div>
</div>
</div>
<!-- 变更日志 -->
<div>
<div class="section-label">变更日志</div>
<div class="change-log" id="changeLog" style="margin-top:8px;">
<div class="change-log__empty">暂无变更,请到左侧添加或移除商品</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="actions">
<a class="btn btn--ghost" href="03-checkout.html">放弃修正</a>
<button class="btn btn--primary" onclick="applyChanges()">
&#x2705; 应用修正并返回结算
</button>
</div>
</div>
</div>
</div>
<script>
/* ==================== Mock 数据 ==================== */
var currentItems = [
{ id: 1, name: '红烧肉', zone: '档口秤', thumb: '&#x1F356;', weight: 180, price: 12.00, status: 'normal' },
{ id: 2, name: '清炒时蔬', zone: '营养秤', thumb: '&#x1F966;', weight: 150, price: 4.00, status: 'normal' },
{ id: 3, name: '鱼香肉丝', zone: '档口秤', thumb: '&#x1F35F;', weight: 160, price: 7.50, status: 'normal' },
{ id: 4, name: '米饭', zone: '营养秤', thumb: '&#x1F35A;', weight: 250, price: 1.60, status: 'normal' },
{ id: 5, name: '冬瓜排骨汤', zone: '档口秤', thumb: '&#x1F372;', weight: 300, price: 1.00, status: 'normal' }
];
var candidates = [
{ id: 101, name: '宫保鸡丁', zone: '档口秤', thumb: '&#x1F357;', price: 9.00 },
{ id: 102, name: '番茄炒蛋', zone: '营养秤', thumb: '&#x1F95B;', price: 5.00 },
{ id: 103, name: '麻婆豆腐', zone: '档口秤', thumb: '&#x1F372;', price: 5.00 },
{ id: 104, name: '紫菜蛋花汤', zone: '营养秤', thumb: '&#x1F372;', price: 2.00 },
{ id: 105, name: '蒜蓉西兰花', zone: '营养秤', thumb: '&#x1F966;', price: 4.00 },
{ id: 106, name: '清蒸鲈鱼', zone: '档口秤', thumb: '&#x1F41F;', price: 12.50 },
{ id: 107, name: '紫米饭', zone: '营养秤', thumb: '&#x1F35A;', price: 1.50 },
{ id: 108, name: '豆浆', zone: '营养秤', thumb: '&#x1F95B;', price: 1.00 },
{ id: 109, name: '青椒土豆丝', zone: '档口秤', thumb: '&#x1F954;', price: 4.50 },
{ id: 110, name: '回锅肉', zone: '档口秤', thumb: '&#x1F356;', price: 11.00 },
{ id: 111, name: '凉拌黄瓜', zone: '营养秤', thumb: '&#x1F952;', price: 3.00 },
{ id: 112, name: '番茄蛋汤', zone: '档口秤', thumb: '&#x1F372;', price: 1.50 },
{ id: 113, name: '酸菜鱼', zone: '档口秤', thumb: '&#x1F41F;', price: 14.00 },
{ id: 114, name: '馒头', zone: '营养秤', thumb: '&#x1F35E;', price: 0.80 }
];
var changeLog = [];
function subtotal(it) {
return it.weight ? it.weight / 100 * it.price : it.price;
}
/* 渲染当前商品列表(对齐 03-checkout 商品行样式) */
function renderCurrent() {
var grouped = { '营养秤': [], '档口秤': [] };
currentItems.forEach(function(it) {
if (!grouped[it.zone]) grouped[it.zone] = [];
grouped[it.zone].push(it);
});
var html = '<div class="table-head">'
+ '<span>#</span>'
+ '<span class="table-head__name">餐品名称 / 单价</span>'
+ '<span class="table-head__weight">取餐量</span>'
+ '<span class="table-head__price">金额</span>'
+ '<span></span>'
+ '</div>';
var seq = 0;
['营养秤', '档口秤'].forEach(function(zone) {
var items = grouped[zone] || [];
if (items.length === 0) return;
var zoneLabel = zone === '营养秤' ? '餐线菜品' : '档口菜品';
var zoneIcon = zone === '营养秤' ? '&#x1F95C;' : '&#x2696;&#xFE0F;';
var zoneTotal = items.reduce(function(s, it) {
return s + (it.status !== 'removed' ? subtotal(it) : 0);
}, 0);
html += '<div class="zone-group">'
+ '<div class="zone-header">'
+ '<span class="zone-header__name">' + zoneIcon + ' ' + zoneLabel
+ '<span class="zone-header__count">' + items.length + ' 件</span>'
+ '</span>'
+ '<span class="zone-header__total">小计 &#xFFE5;' + zoneTotal.toFixed(2) + '</span>'
+ '</div>';
items.forEach(function(it) {
seq++;
var actionBtn = it.status === 'removed'
? '<div class="item-card__action item-card__action--restore" onclick="restoreItem(' + it.id + ')" title="恢复">&#x21BA;</div>'
: '<div class="item-card__action item-card__action--remove" onclick="removeItem(' + it.id + ')" title="移除">&#x2212;</div>';
var badge = '';
if (it.status === 'added') badge = '<span class="change-badge change-badge--add">新加</span>';
if (it.status === 'removed') badge = '<span class="change-badge change-badge--remove">已移除</span>';
var weightText = it.weight ? '取 ' + it.weight + 'g' : '需称重';
var unitPrice = it.weight ? '&#xFFE5;' + it.price.toFixed(2) + '/100g' : '&#xFFE5;' + it.price.toFixed(2) + '/份';
html += '<div class="item-card ' + (it.status === 'added' ? 'added' : '') + (it.status === 'removed' ? ' removed' : '') + '">'
+ '<div class="item-card__seq">' + seq + '</div>'
+ '<div class="item-card__info">'
+ '<span class="item-card__name">' + it.name + badge + '</span>'
+ '<span class="item-card__unit-price">' + unitPrice + '</span>'
+ '</div>'
+ '<span class="item-card__weight">' + weightText + '</span>'
+ '<div class="item-card__price">&#xFFE5;' + subtotal(it).toFixed(2) + '</div>'
+ actionBtn
+ '</div>';
});
html += '</div>';
});
document.getElementById('currentList').innerHTML = html;
}
/* 渲染候选添加商品 */
function renderCandidates() {
var grouped = { '营养秤': [], '档口秤': [] };
candidates.forEach(function(it) {
grouped[it.zone].push(it);
});
document.getElementById('candidateScale').innerHTML = grouped['营养秤'].map(function(it) {
return candidateHtml(it);
}).join('');
document.getElementById('candidateStall').innerHTML = grouped['档口秤'].map(function(it) {
return candidateHtml(it);
}).join('');
}
function candidateHtml(it) {
return '<div class="candidate-item" data-name="' + it.name + '">'
+ '<div class="candidate-item__thumb">' + it.thumb + '</div>'
+ '<div class="candidate-item__name">' + it.name + '</div>'
+ '<div class="candidate-item__meta">&#xFFE5;' + it.price.toFixed(2) + '/100g</div>'
+ '<div class="candidate-item__add" onclick="addItem(' + it.id + ')">+ 添加</div>'
+ '</div>';
}
/* 搜索过滤 */
function filterCandidates() {
var keyword = document.getElementById('searchInput').value.toLowerCase();
document.querySelectorAll('.candidate-item').forEach(function(el) {
var name = el.dataset.name.toLowerCase();
el.style.display = name.indexOf(keyword) >= 0 ? '' : 'none';
});
}
/* Tab 切换 */
function switchTab(type) {
document.querySelectorAll('.tab').forEach(function(el, idx) {
el.classList.toggle('active', (type === 'current' && idx === 0) || (type === 'add' && idx === 1));
});
document.getElementById('currentList').style.display = type === 'current' ? '' : 'none';
document.getElementById('addList').style.display = type === 'add' ? '' : 'none';
}
/* 移除商品(多记) */
function removeItem(id) {
var item = currentItems.filter(function(it) { return it.id === id; })[0];
if (!item) return;
if (item.status === 'added') {
/* 新加的直接删除 */
currentItems = currentItems.filter(function(it) { return it.id !== id; });
changeLog = changeLog.filter(function(l) { return l.id !== id; });
} else {
item.status = 'removed';
changeLog.push({
id: id, type: 'remove', name: item.name,
amount: -subtotal(item), time: getTime()
});
}
renderCurrent();
renderLog();
recalc();
}
/* 恢复商品 */
function restoreItem(id) {
var item = currentItems.filter(function(it) { return it.id === id; })[0];
if (!item) return;
item.status = 'normal';
changeLog = changeLog.filter(function(l) { return l.id !== id; });
renderCurrent();
renderLog();
recalc();
}
/* 添加商品 */
function addItem(candidateId) {
var cand = candidates.filter(function(c) { return c.id === candidateId; })[0];
if (!cand) return;
/* 弹窗输入重量 */
var weight = prompt('请输入 "' + cand.name + '" 的重量(克):', '150');
if (!weight) return;
var w = parseFloat(weight) || 150;
var newItem = {
id: Date.now(), name: cand.name, zone: cand.zone, thumb: cand.thumb,
weight: w, price: cand.price, status: 'added'
};
currentItems.push(newItem);
changeLog.push({
id: newItem.id, type: 'add', name: cand.name,
amount: subtotal(newItem), time: getTime()
});
renderCurrent();
renderLog();
recalc();
/* 切回当前订单 Tab */
switchTab('current');
}
function getTime() {
var d = new Date();
return String(d.getHours()).padStart(2, '0') + ':' + String(d.getMinutes()).padStart(2, '0') + ':' + String(d.getSeconds()).padStart(2, '0');
}
/* 变更日志 */
function renderLog() {
var el = document.getElementById('changeLog');
if (changeLog.length === 0) {
el.innerHTML = '<div class="change-log__empty">暂无变更,请到左侧添加或移除商品</div>';
return;
}
el.innerHTML = changeLog.map(function(l) {
var icon = l.type === 'add' ? '&#x2795;' : '&#x2796;';
var cls = l.type === 'add' ? 'add' : 'remove';
return '<div class="log-item">'
+ '<span class="log-item__icon">' + icon + '</span>'
+ '<div class="log-item__text">'
+ '<span class="log-item__name">' + l.name + '</span> '
+ '<span class="log-item__amount log-item__amount--' + cls + '">(' + (l.amount > 0 ? '+' : '') + '&#xFFE5;' + l.amount.toFixed(2) + ')</span>'
+ ' <span class="log-item__time">' + l.time + '</span>'
+ '</div>'
+ '</div>';
}).join('');
}
/* 重新计算金额 */
function recalc() {
var original = 46.60;
var newTotal = currentItems.reduce(function(s, it) {
return s + (it.status === 'removed' ? 0 : subtotal(it));
}, 0);
var change = newTotal - original;
var discount = 5.00;
var newPayable = newTotal - discount;
document.getElementById('changeAmount').innerHTML = (change >= 0 ? '+' : '') + '&#xFFE5;' + change.toFixed(2);
document.getElementById('changeAmount').style.color = change >= 0 ? '#4ade80' : '#ff6b6b';
document.getElementById('newAmount').textContent = '¥' + newTotal.toFixed(2);
document.getElementById('newPayable').innerHTML = '&#xFFE5;' + newPayable.toFixed(2);
var deltaRow = document.getElementById('deltaRow');
deltaRow.className = change >= 0 ? 'compare-row compare-row--delta' : 'compare-row compare-row--delta compare-row--delta-minus';
}
/* 应用变更 */
function applyChanges() {
if (changeLog.length === 0) {
alert('暂无变更,可直接返回结算');
return;
}
if (confirm('确认应用本次修正?\n变更:' + changeLog.length + ' 项\n新应付金额:¥' + (currentItems.reduce(function(s, it) { return s + (it.status === 'removed' ? 0 : subtotal(it)); }, 0) - 5).toFixed(2))) {
alert('修正已应用,返回结算页');
window.location.href = '03-checkout.html';
}
}
/* 初始化 */
renderCurrent();
renderCandidates();
recalc();
</script>
</body>
</html>
@@ -59,152 +59,15 @@
color: rgba(255, 255, 255, 0.5);
}
/* 主体:左右两列 */
/* 主体:单列小票预览 */
.page-body {
display: grid;
grid-template-columns: 340px 1fr;
display: flex;
flex-direction: column;
height: calc(100% - 44px);
overflow: hidden;
}
/* ===== 左列:订单列表 ===== */
.left-col {
display: flex;
flex-direction: column;
border-right: 1px solid rgba(255, 255, 255, 0.06);
background: rgba(26, 43, 74, 0.3);
}
.filter-bar {
padding: 12px 16px;
display: flex;
gap: 8px;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
flex-shrink: 0;
}
.filter-select {
flex: 1;
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
padding: 6px 10px;
font-size: 12px;
color: rgba(255, 255, 255, 0.85);
font-family: inherit;
outline: none;
cursor: pointer;
}
.filter-select:focus { border-color: #4a90d9; }
.order-list {
flex: 1;
overflow-y: auto;
padding: 10px 12px;
display: flex;
flex-direction: column;
gap: 8px;
scrollbar-width: none;
}
.order-list::-webkit-scrollbar { display: none; }
.order-card {
background: #1a2b4a;
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 8px;
padding: 10px 12px;
cursor: pointer;
transition: all 0.2s;
position: relative;
}
.order-card:hover {
border-color: rgba(74, 144, 217, 0.4);
background: rgba(74, 144, 217, 0.08);
}
.order-card.active {
border-color: #4a90d9;
background: rgba(74, 144, 217, 0.12);
box-shadow: 0 0 0 1px rgba(74, 144, 217, 0.3);
}
.order-card.printed {
opacity: 0.55;
}
.order-card__row1 {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
}
.order-card__id {
font-size: 12px;
font-weight: 600;
color: rgba(255, 255, 255, 0.9);
font-family: Menlo, Consolas, monospace;
}
.meal-tag {
font-size: 10px;
line-height: 1;
padding: 3px 7px;
border-radius: 9px;
font-weight: 600;
letter-spacing: 0.3px;
}
.meal-tag--breakfast {
background: rgba(250, 140, 22, 0.18);
color: #fb923c;
border: 1px solid rgba(250, 140, 22, 0.35);
}
.meal-tag--lunch {
background: rgba(37, 99, 235, 0.18);
color: #60a5fa;
border: 1px solid rgba(37, 99, 235, 0.35);
}
.meal-tag--dinner {
background: rgba(34, 197, 94, 0.18);
color: #4ade80;
border: 1px solid rgba(34, 197, 94, 0.35);
}
.order-card__row2 {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
}
.order-card__time {
font-family: Menlo, Consolas, monospace;
}
.order-card__amount {
font-size: 14px;
font-weight: 700;
color: #0AC4A8;
}
.order-card__status {
position: absolute;
top: 8px;
right: 8px;
font-size: 9px;
line-height: 1;
padding: 3px 6px;
border-radius: 8px;
font-weight: 600;
letter-spacing: 0.3px;
}
.order-card__status--printed {
background: rgba(255, 255, 255, 0.06);
color: rgba(255, 255, 255, 0.4);
border: 1px solid rgba(255, 255, 255, 0.12);
}
.order-card__status--pending {
background: rgba(234, 88, 12, 0.18);
color: #fb923c;
border: 1px solid rgba(234, 88, 12, 0.35);
}
/* ===== 右列:小票预览 ===== */
.right-col {
display: flex;
flex-direction: column;
overflow: hidden;
}
/* ===== 小票预览区 ===== */
.receipt-stage {
flex: 1;
padding: 24px 32px;
@@ -549,7 +412,7 @@
<!-- 顶部导航 -->
<div class="top-bar">
<a class="back-btn" href="index.html">&#x25C0; 返回</a>
<a class="back-btn" href="index.html">&#x25C0; 返回主页</a>
<span class="top-bar__title">打印小票预览</span>
<span class="top-bar__meta" id="topMeta">2026-08-03</span>
</div>
@@ -557,31 +420,11 @@
<!-- 主体 -->
<div class="page-body">
<!-- 左列:订单列表 -->
<div class="left-col">
<div class="filter-bar">
<select class="filter-select" id="mealFilter" onchange="renderOrderList()">
<option value="all">全部餐次</option>
<option value="breakfast">早餐</option>
<option value="lunch">午餐</option>
<option value="dinner">晚餐</option>
</select>
<select class="filter-select" id="statusFilter" onchange="renderOrderList()">
<option value="all">全部状态</option>
<option value="pending">未打印</option>
<option value="printed">已打印</option>
</select>
</div>
<div class="order-list" id="orderList"></div>
</div>
<!-- 右列:小票预览 -->
<div class="right-col">
<div class="receipt-stage" id="receiptStage"></div>
<div class="action-bar">
<button class="btn btn--ghost" onclick="window.location.href='index.html'">&#x25C0; 返回</button>
<button class="btn btn--success" id="printBtn" onclick="handlePrint()">&#x1F5A8;&#xFE0F; 打印小票</button>
</div>
<!-- 小票预览区 -->
<div class="receipt-stage" id="receiptStage"></div>
<div class="action-bar">
<button class="btn btn--ghost" onclick="window.location.href='index.html'">&#x25C0; 返回主页</button>
<button class="btn btn--success" id="printBtn" onclick="handlePrint()">&#x1F5A8;&#xFE0F; 打印小票</button>
</div>
</div>
@@ -592,121 +435,27 @@
<div class="toast" id="toast"></div>
<script>
/* ==================== Mock 订单数据 ==================== */
var mockOrders = [
{
id: 'CO-20260803-001',
mealType: 'lunch',
mealLabel: '午餐',
line: '一楼',
cashier: '张三',
time: '2026-08-03 12:15:30',
payTime: '2026-08-03 12:15:35',
items: [
/* 小计 = 克重 ÷ 100 × 单价(100g) */
{ name: '宫保鸡丁', zone: '档口秤', weight: 200, price: 9.00, qty: 1 },
{ name: '番茄炒蛋', zone: '营养秤', weight: 150, price: 5.00, qty: 1 },
{ name: '米饭', zone: '营养秤', weight: 250, price: 1.60, qty: 1 },
{ name: '紫菜蛋花汤', zone: '档口秤', weight: 300, price: 2.00, qty: 1 }
],
total: 35.50, discount: 3.00, payable: 32.50, paid: 32.50,
payType: '会员支付', payMethod: '人脸支付', balance: 1280.50,
nutrition: { calories: 685, protein: 28, fat: 18, carb: 95, score: 82 },
printed: true
},
{
id: 'CO-20260803-008',
mealType: 'breakfast',
mealLabel: '早餐',
line: '一楼',
cashier: '张三',
time: '2026-08-03 07:42:18',
payTime: '2026-08-03 07:42:23',
items: [
{ name: '豆浆', zone: '营养秤', weight: 300, price: 1.00, qty: 1 },
{ name: '油条', zone: '档口秤', weight: 240, price: 2.50, qty: 2 },
{ name: '茶叶蛋', zone: '营养秤', weight: 60, price: 4.00, qty: 1 }
],
total: 11.40, discount: 0, payable: 11.40, paid: 11.40,
payType: '会员支付', payMethod: '人脸支付', balance: 1292.50,
nutrition: { calories: 425, protein: 15, fat: 12, carb: 60, score: 75 },
printed: true
},
{
id: 'CO-20260803-015',
mealType: 'lunch',
mealLabel: '午餐',
line: 'A 区 2 号餐线',
cashier: '李四',
time: '2026-08-03 12:32:45',
payTime: '2026-08-03 12:32:50',
items: [
{ name: '红烧肉', zone: '档口秤', weight: 180, price: 12.00, qty: 1 },
{ name: '清炒时蔬', zone: '营养秤', weight: 150, price: 4.00, qty: 1 },
{ name: '鱼香肉丝', zone: '档口秤', weight: 160, price: 7.50, qty: 1 },
{ name: '米饭', zone: '营养秤', weight: 250, price: 1.60, qty: 1 },
{ name: '冬瓜排骨汤', zone: '档口秤', weight: 300, price: 1.00, qty: 1 }
],
total: 46.60, discount: 5.00, payable: 41.60, paid: 41.60,
payType: '会员支付', payMethod: '人脸支付', balance: 1240.50,
nutrition: { calories: 720, protein: 35, fat: 28, carb: 88, score: 88 },
printed: false
},
{
id: 'CO-20260803-022',
mealType: 'dinner',
mealLabel: '晚餐',
line: '一楼',
cashier: '王五',
time: '2026-08-03 18:15:20',
payTime: '2026-08-03 18:15:25',
items: [
{ name: '清蒸鲈鱼', zone: '档口秤', weight: 200, price: 12.50, qty: 1 },
{ name: '蒜蓉西兰花', zone: '营养秤', weight: 150, price: 4.00, qty: 1 },
{ name: '紫米饭', zone: '营养秤', weight: 200, price: 1.50, qty: 1 }
],
total: 34.00, discount: 0, payable: 34.00, paid: 34.00,
payType: '扫码支付', payMethod: '微信支付',
nutrition: { calories: 510, protein: 32, fat: 14, carb: 65, score: 90 },
printed: false
},
{
id: 'CO-20260803-029',
mealType: 'lunch',
mealLabel: '午餐',
line: 'A 区 3 号餐线',
cashier: '张三',
time: '2026-08-03 12:48:10',
payTime: '2026-08-03 12:48:15',
items: [
{ name: '番茄炒蛋', zone: '营养秤', weight: 150, price: 5.00, qty: 1 },
{ name: '麻婆豆腐', zone: '档口秤', weight: 180, price: 5.00, qty: 1 },
{ name: '米饭', zone: '营养秤', weight: 250, price: 1.60, qty: 1 },
{ name: '番茄蛋汤', zone: '档口秤', weight: 280, price: 1.50, qty: 1 }
],
total: 24.70, discount: 0, payable: 24.70, paid: 24.70,
payType: '会员支付', payMethod: '人脸支付', balance: 1187.50,
nutrition: { calories: 480, protein: 22, fat: 15, carb: 70, score: 78 },
printed: false
},
{
id: 'CO-20260803-035',
mealType: 'breakfast',
mealLabel: '早餐',
line: 'A 区 2 号餐线',
cashier: '李四',
time: '2026-08-03 08:15:30',
payTime: '2026-08-03 08:15:33',
items: [
{ name: '皮蛋瘦肉粥', zone: '档口秤', weight: 350, price: 1.40, qty: 1 },
{ name: '鲜肉包子', zone: '营养秤', weight: 150, price: 2.00, qty: 1 }
],
total: 7.90, discount: 0, payable: 7.90, paid: 7.90,
payType: '扫码支付', payMethod: '支付宝支付',
nutrition: { calories: 320, protein: 12, fat: 8, carb: 48, score: 70 },
printed: false
}
];
/* ==================== Mock 订单数据(仅展示样本) ==================== */
var mockOrder = {
id: 'CO-20260803-001',
mealType: 'lunch',
mealLabel: '午餐',
line: '一楼',
cashier: '张三',
time: '2026-08-03 12:15:30',
payTime: '2026-08-03 12:15:35',
items: [
/* 小计 = 克重 ÷ 100 × 单价(100g) */
{ name: '宫保鸡丁', zone: '档口秤', weight: 200, price: 9.00, qty: 1 },
{ name: '番茄炒蛋', zone: '营养秤', weight: 150, price: 5.00, qty: 1 },
{ name: '米饭', zone: '营养秤', weight: 250, price: 1.60, qty: 1 },
{ name: '紫菜蛋花汤', zone: '档口秤', weight: 300, price: 2.00, qty: 1 }
],
total: 35.50, discount: 3.00, payable: 32.50, paid: 32.50,
payType: '会员支付', payMethod: '人脸支付', balance: 1280.50,
nutrition: { calories: 685, protein: 28, fat: 18, carb: 95, score: 82 },
printed: true
};
/* 食堂抬头 */
var canteenInfo = {
@@ -715,57 +464,9 @@
phone: '023-7788-XXXX'
};
var currentOrderId = mockOrders[0].id;
/* ==================== 渲染:订单列表 ==================== */
function renderOrderList() {
var mealFilter = document.getElementById('mealFilter').value;
var statusFilter = document.getElementById('statusFilter').value;
var filtered = mockOrders.filter(function(o) {
if (mealFilter !== 'all' && o.mealType !== mealFilter) return false;
if (statusFilter === 'pending' && o.printed) return false;
if (statusFilter === 'printed' && !o.printed) return false;
return true;
});
var listEl = document.getElementById('orderList');
if (filtered.length === 0) {
listEl.innerHTML = '<div style="text-align:center;padding:24px 8px;color:rgba(255,255,255,0.3);font-size:12px;">无符合条件的订单</div>';
return;
}
var html = filtered.map(function(o) {
var mealTagClass = 'meal-tag--' + o.mealType;
var printedClass = o.printed ? ' printed' : '';
var activeClass = o.id === currentOrderId ? ' active' : '';
var statusHtml = o.printed
? '<span class="order-card__status order-card__status--printed">已打印</span>'
: '<span class="order-card__status order-card__status--pending">未打印</span>';
return '<div class="order-card' + activeClass + printedClass + '" onclick="selectOrder(\'' + o.id + '\')">'
+ statusHtml
+ '<div class="order-card__row1">'
+ '<span class="order-card__id">' + o.id + '</span>'
+ '<span class="meal-tag ' + mealTagClass + '">' + o.mealLabel + '</span>'
+ '</div>'
+ '<div class="order-card__row2">'
+ '<span class="order-card__time">' + o.time + '</span>'
+ '<span class="order-card__amount">¥' + o.payable.toFixed(2) + '</span>'
+ '</div>'
+ '</div>';
}).join('');
listEl.innerHTML = html;
}
/* ==================== 渲染:小票预览 ==================== */
function renderReceipt() {
var order = mockOrders.filter(function(o) { return o.id === currentOrderId; })[0];
if (!order) {
document.getElementById('receiptStage').innerHTML = '<div style="color:rgba(255,255,255,0.3);font-size:12px;">请选择左侧订单查看小票</div>';
updatePrintBtn();
return;
}
var order = mockOrder;
/* 按分区分组 */
var zoneOrder = ['营养秤', '档口秤'];
@@ -898,7 +599,6 @@
+ '</div>';
document.getElementById('receiptStage').innerHTML = html;
updatePrintBtn();
}
/* 简化版二维码 SVG (21x21 模块,模拟外观) */
@@ -973,37 +673,9 @@
return generateQRCodeSVG(matrix);
}
/* 切换订单 */
function selectOrder(orderId) {
currentOrderId = orderId;
renderOrderList();
renderReceipt();
}
/* 打印按钮状态切换 */
function updatePrintBtn() {
var order = mockOrders.filter(function(o) { return o.id === currentOrderId; })[0];
var btn = document.getElementById('printBtn');
if (order && order.printed) {
btn.className = 'btn btn--primary';
btn.innerHTML = '&#x1F5A8;&#xFE0F; 重新打印';
} else {
btn.className = 'btn btn--success';
btn.innerHTML = '&#x1F5A8;&#xFE0F; 打印小票';
}
}
/* 打印处理 */
function handlePrint() {
var order = mockOrders.filter(function(o) { return o.id === currentOrderId; })[0];
if (!order) {
showToast('请先选择订单', 'warn');
return;
}
order.printed = true;
renderOrderList();
updatePrintBtn();
showToast('订单 ' + order.id + ' 小票打印成功', 'success');
showToast('订单 ' + mockOrder.id + ' 小票打印成功', 'success');
}
/* Toast */
@@ -1019,7 +691,6 @@
}
/* 初始化 */
renderOrderList();
renderReceipt();
</script>
@@ -6,7 +6,6 @@
<title>结算设备 - 蚁熊智能餐养平台</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
/* 外层视口:全屏深色背景,承载居中 PAD 外壳 */
body {
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
background: #05080f;
@@ -18,7 +17,6 @@
justify-content: center;
padding: 20px;
}
/* PAD 设备外壳 */
.device-frame {
width: 1280px;
height: 720px;
@@ -46,99 +44,137 @@
font-weight: 600;
color: rgba(255, 255, 255, 0.85);
}
/* 主内容区:三菜单网格 */
/* 主内容:左右两区(用户屏 / 收银员屏) */
.main-content {
flex: 1;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 28px;
padding: 56px 80px;
height: calc(100% - 44px);
align-content: center;
grid-template-columns: 1fr 1fr;
gap: 20px;
padding: 20px 28px;
overflow: hidden;
}
/* 屏幕分区 */
.screen-section {
display: flex;
flex-direction: column;
overflow: hidden;
}
.screen-section__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 4px 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
margin-bottom: 12px;
}
.screen-section__title {
font-size: 14px;
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.screen-section__title-bar {
width: 4px;
height: 14px;
border-radius: 2px;
}
.screen-section--user .screen-section__title-bar { background: #0AC4A8; }
.screen-section--cashier .screen-section__title-bar { background: #4a90d9; }
.screen-section__sub {
font-size: 11px;
color: rgba(255, 255, 255, 0.45);
}
.card-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
overflow-y: auto;
scrollbar-width: none;
padding-right: 4px;
}
.card-grid::-webkit-scrollbar { display: none; }
/* 菜单卡片 */
.card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 18px;
padding: 36px 24px;
gap: 10px;
padding: 12px 14px;
background: #1a2b4a;
border-radius: 16px;
border-radius: 10px;
text-decoration: none;
cursor: pointer;
transition: all 0.2s;
border: 1px solid rgba(255, 255, 255, 0.06);
text-align: center;
position: relative;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
border-color: rgba(74, 144, 217, 0.3);
border-color: rgba(74, 144, 217, 0.35);
background: rgba(74, 144, 217, 0.08);
}
.screen-section--user .card:hover {
border-color: rgba(10, 196, 168, 0.35);
background: rgba(10, 196, 168, 0.08);
}
/* 禁用卡片(待开发) */
.card--disabled {
pointer-events: none;
background: rgba(26, 43, 74, 0.4);
opacity: 0.55;
opacity: 0.4;
}
.card--disabled:hover {
transform: none;
box-shadow: none;
border-color: rgba(255, 255, 255, 0.06);
}
/* 图标圆底 */
.card__icon {
font-size: 44px;
width: 84px;
height: 84px;
border-radius: 50%;
background: rgba(74, 144, 217, 0.12);
font-size: 22px;
width: 38px;
height: 38px;
border-radius: 8px;
background: rgba(74, 144, 217, 0.15);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.card--disabled .card__icon {
background: rgba(255, 255, 255, 0.04);
.screen-section--user .card__icon {
background: rgba(10, 196, 168, 0.15);
}
.card__body { flex: 1; min-width: 0; }
.card__title {
font-size: 17px;
font-size: 13px;
font-weight: 600;
color: #fff;
}
.card--disabled .card__title {
color: rgba(255, 255, 255, 0.6);
margin-bottom: 2px;
}
.card__desc {
font-size: 12px;
font-size: 10px;
color: rgba(255, 255, 255, 0.45);
line-height: 1.5;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.card--disabled .card__desc {
color: rgba(255, 255, 255, 0.3);
}
/* 右上角状态标签 */
.card__status {
position: absolute;
top: 10px;
right: 10px;
font-size: 10px;
top: 6px;
right: 6px;
font-size: 9px;
line-height: 1;
padding: 4px 8px;
border-radius: 9px;
padding: 3px 6px;
border-radius: 7px;
font-weight: 600;
letter-spacing: 0.3px;
}
.card__status--done {
background: rgba(34, 197, 94, 0.18);
background: rgba(34, 197, 94, 0.2);
color: #4ade80;
border: 1px solid rgba(34, 197, 94, 0.35);
border: 1px solid rgba(34, 197, 94, 0.4);
}
.card__status--pending {
background: rgba(234, 88, 12, 0.18);
color: #fb923c;
border: 1px solid rgba(234, 88, 12, 0.35);
.card__status--core {
background: rgba(251, 191, 36, 0.2);
color: #fbbf24;
border: 1px solid rgba(251, 191, 36, 0.4);
}
</style>
</head>
@@ -151,32 +187,140 @@
<span class="top-bar__title">结算设备</span>
</div>
<!-- 主内容:三菜单卡片 -->
<!-- 主内容:左右两屏 -->
<div class="main-content">
<!-- 1. 员工登录(待开发) -->
<a class="card card--disabled" href="javascript:void(0)">
<span class="card__status card__status--pending">待开发</span>
<div class="card__icon">&#x1F510;</div>
<div class="card__title">员工登录</div>
<div class="card__desc">人脸识别 / 账号密码登录</div>
</a>
<!-- 左区:用户屏(副屏) -->
<div class="screen-section screen-section--user">
<div class="screen-section__header">
<div class="screen-section__title">
<span class="screen-section__title-bar"></span>
&#x1F4BB; 用户屏(副屏)
</div>
<span class="screen-section__sub">面向就餐人员展示</span>
</div>
<!-- 2. 结算台(待开发) -->
<a class="card card--disabled" href="javascript:void(0)">
<span class="card__status card__status--pending">待开发</span>
<div class="card__icon">&#x1F4B3;</div>
<div class="card__title">结算台</div>
<div class="card__desc">智能结算与餐卡支付</div>
</a>
<div class="card-grid">
<a class="card" href="user-01-idle.html">
<span class="card__status card__status--done">U01</span>
<div class="card__icon">&#x1F44B;</div>
<div class="card__body">
<div class="card__title">待机欢迎</div>
<div class="card__desc">欢迎语 + 时钟 + 营养宣传</div>
</div>
</a>
<a class="card" href="user-02-checkout-sync.html">
<span class="card__status card__status--done">U02</span>
<div class="card__icon">&#x1F6CD;&#xFE0F;</div>
<div class="card__body">
<div class="card__title">取餐明细展示</div>
<div class="card__desc">同步商品列表 + 营养摘要</div>
</div>
</a>
<a class="card" href="user-03-paying.html">
<span class="card__status card__status--done">U03</span>
<div class="card__icon">&#x1F4F1;</div>
<div class="card__body">
<div class="card__title">支付引导</div>
<div class="card__desc">4 种支付方式引导切换</div>
</div>
</a>
<a class="card" href="user-04-success.html">
<span class="card__status card__status--done">U04</span>
<div class="card__icon">&#x2705;</div>
<div class="card__body">
<div class="card__title">支付成功</div>
<div class="card__desc">大金额 + 营养评分 + 引导</div>
</div>
</a>
</div>
</div>
<!-- 3. 打印小票(已设计) -->
<a class="card" href="02-print-receipt.html">
<span class="card__status card__status--done">已设计</span>
<div class="card__icon">&#x1F5A8;&#xFE0F;</div>
<div class="card__title">打印小票</div>
<div class="card__desc">餐后结算小票预览与打印</div>
</a>
<!-- 右区:收银员屏(主屏) -->
<div class="screen-section screen-section--cashier">
<div class="screen-section__header">
<div class="screen-section__title">
<span class="screen-section__title-bar"></span>
&#x1F9D1;&#x200D;&#x1F4BB; 收银员屏(主屏)
</div>
<span class="screen-section__sub">收银员全流程操作</span>
</div>
<div class="card-grid">
<a class="card" href="01-login.html">
<span class="card__status card__status--done">01</span>
<div class="card__icon">&#x1F510;</div>
<div class="card__body">
<div class="card__title">收银员登录</div>
<div class="card__desc">人脸识别登录 + 班次信息</div>
</div>
</a>
<a class="card" href="02-standby.html">
<span class="card__status card__status--done">02</span>
<div class="card__icon">&#x1F4CB;</div>
<div class="card__body">
<div class="card__title">待机页</div>
<div class="card__desc">时钟 + 数据预览 + 入口</div>
</div>
</a>
<a class="card" href="03-checkout.html">
<span class="card__status card__status--core">03 核心</span>
<div class="card__icon">&#x1F4B3;</div>
<div class="card__body">
<div class="card__title">结算页</div>
<div class="card__desc">4 种支付 + 商品 + 补齐</div>
</div>
</a>
<a class="card" href="04-pay-success.html">
<span class="card__status card__status--done">04</span>
<div class="card__icon">&#x1F389;</div>
<div class="card__body">
<div class="card__title">支付成功</div>
<div class="card__desc">打印 + 新单 + 详情入口</div>
</div>
</a>
<a class="card" href="05-orders.html">
<span class="card__status card__status--done">05</span>
<div class="card__icon">&#x1F4DA;</div>
<div class="card__body">
<div class="card__title">订单列表</div>
<div class="card__desc">今日订单 + 筛选 + 退款</div>
</div>
</a>
<a class="card" href="06-order-detail.html">
<span class="card__status card__status--done">06</span>
<div class="card__icon">&#x1F4C4;</div>
<div class="card__body">
<div class="card__title">订单详情</div>
<div class="card__desc">明细 + 退款流程 + 重打</div>
</div>
</a>
<a class="card" href="07-statistics.html">
<span class="card__status card__status--done">07</span>
<div class="card__icon">&#x1F4CA;</div>
<div class="card__body">
<div class="card__title">运营数据统计</div>
<div class="card__desc">营收 + 餐次 + Top + 时段</div>
</div>
</a>
<a class="card" href="08-reconcile.html">
<span class="card__status card__status--done">08</span>
<div class="card__icon">&#x270F;&#xFE0F;</div>
<div class="card__body">
<div class="card__title">补齐明细</div>
<div class="card__desc">漏记添加 / 多记删除</div>
</div>
</a>
<a class="card" href="09-print-receipt.html">
<span class="card__status card__status--done">09</span>
<div class="card__icon">&#x1F5A8;&#xFE0F;</div>
<div class="card__body">
<div class="card__title">打印小票</div>
<div class="card__desc">餐后小票预览与打印</div>
</div>
</a>
</div>
</div>
</div>
@@ -0,0 +1,339 @@
<!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;
}
/* 用户屏外壳:竖屏式(实际副屏为竖式) */
.device-frame {
width: 1280px;
height: 720px;
background: linear-gradient(180deg, #0e1326 0%, #1a2b4a 50%, #0e1326 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 背景装饰:营养元素 */
.bg-deco {
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0.06;
background-image:
radial-gradient(circle at 20% 20%, #4a90d9 0%, transparent 30%),
radial-gradient(circle at 80% 80%, #0AC4A8 0%, transparent 30%),
radial-gradient(circle at 50% 50%, #fbbf24 0%, transparent 20%);
}
.bg-deco__icon {
position: absolute;
font-size: 50px;
opacity: 0.1;
}
.bg-deco__icon--1 { top: 10%; left: 5%; }
.bg-deco__icon--2 { top: 15%; right: 8%; }
.bg-deco__icon--3 { bottom: 20%; left: 8%; }
.bg-deco__icon--4 { bottom: 15%; right: 6%; }
/* 顶部:食堂信息 */
.header {
padding: 30px 60px 20px;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 2;
}
.canteen-info { display: flex; align-items: center; gap: 14px; }
.canteen-logo {
width: 56px;
height: 56px;
border-radius: 14px;
background: linear-gradient(135deg, #4a90d9, #0AC4A8);
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
box-shadow: 0 4px 16px rgba(74, 144, 217, 0.3);
}
.canteen-text { display: flex; flex-direction: column; gap: 2px; }
.canteen-name {
font-size: 26px;
font-weight: 700;
color: #fff;
letter-spacing: 1px;
}
.canteen-sub {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
letter-spacing: 0.5px;
}
.weather {
text-align: right;
font-size: 12px;
color: rgba(255, 255, 255, 0.55);
line-height: 1.6;
}
.weather__icon { font-size: 22px; }
.weather__temp { color: #fff; font-size: 16px; font-weight: 600; }
/* 中央:大时钟 */
.clock-area {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 14px;
z-index: 2;
}
.big-time {
font-size: 144px;
font-weight: 200;
color: #fff;
font-family: Menlo, Consolas, "Courier New", monospace;
line-height: 1;
letter-spacing: 6px;
text-shadow: 0 4px 30px rgba(74, 144, 217, 0.4);
}
.big-date {
font-size: 18px;
color: rgba(255, 255, 255, 0.65);
letter-spacing: 1px;
display: flex;
align-items: center;
gap: 16px;
}
.meal-tag-large {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 16px;
border-radius: 18px;
font-size: 14px;
font-weight: 600;
}
.meal-tag-large--lunch {
background: rgba(37, 99, 235, 0.25);
color: #60a5fa;
border: 1px solid rgba(37, 99, 235, 0.5);
}
/* 欢迎横幅 */
.welcome-banner {
padding: 0 60px;
text-align: center;
z-index: 2;
}
.welcome-text {
font-size: 32px;
font-weight: 700;
background: linear-gradient(90deg, #4a90d9, #0AC4A8, #4ade80);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: 4px;
margin-bottom: 8px;
}
.welcome-sub {
font-size: 14px;
color: rgba(255, 255, 255, 0.55);
letter-spacing: 2px;
}
/* 营养宣传区 */
.nutrition-promo {
padding: 24px 60px 30px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
z-index: 2;
}
.promo-card {
padding: 18px 16px;
background: rgba(26, 43, 74, 0.5);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 14px;
backdrop-filter: blur(10px);
text-align: center;
transition: all 0.3s;
}
.promo-card:hover {
transform: translateY(-3px);
border-color: rgba(74, 144, 217, 0.4);
}
.promo-card__icon {
font-size: 36px;
margin-bottom: 6px;
}
.promo-card__value {
font-size: 22px;
font-weight: 700;
color: #fff;
font-family: Menlo, Consolas, monospace;
}
.promo-card__unit {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
font-weight: 400;
}
.promo-card__label {
font-size: 12px;
color: rgba(255, 255, 255, 0.65);
margin-top: 4px;
}
/* 底部:滚动提示 */
.footer-tip {
padding: 12px 60px 18px;
text-align: center;
z-index: 2;
font-size: 13px;
color: rgba(255, 255, 255, 0.55);
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.footer-tip__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #52c41a;
box-shadow: 0 0 8px #52c41a;
animation: blink 1.5s infinite;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
</style>
</head>
<body>
<div class="device-frame">
<div class="bg-deco">
<div class="bg-deco__icon bg-deco__icon--1">&#x1F34E;</div>
<div class="bg-deco__icon bg-deco__icon--2">&#x1F957;</div>
<div class="bg-deco__icon bg-deco__icon--3">&#x1F346;</div>
<div class="bg-deco__icon bg-deco__icon--4">&#x1F95B;</div>
</div>
<!-- 顶部:食堂信息 -->
<div class="header">
<div class="canteen-info">
<div class="canteen-logo">&#x1F37D;</div>
<div class="canteen-text">
<div class="canteen-name">数味餐厅</div>
<div class="canteen-sub">SHUWEI CANTEEN · 智慧营养 · 健康生活</div>
</div>
</div>
<div class="weather">
<div><span class="weather__icon">&#x2600;&#xFE0F;</span> 西安 晴</div>
<div class="weather__temp">28°C</div>
<div style="font-size:11px;color:rgba(255,255,255,0.4);">空气优 · 湿度 45%</div>
</div>
</div>
<!-- 中央:大时钟 -->
<div class="clock-area">
<div class="big-time" id="bigTime">12:30:45</div>
<div class="big-date" id="bigDate">
2026 年 08 月 06 日 · 周四
<span class="meal-tag-large meal-tag-large--lunch" id="mealTag">&#x1F96A; 午餐时段</span>
</div>
</div>
<!-- 欢迎横幅 -->
<div class="welcome-banner">
<div class="welcome-text">合理膳食 · 均衡营养</div>
</div>
<!-- 营养宣传卡片 -->
<div class="nutrition-promo">
<div class="promo-card">
<div class="promo-card__icon">&#x1F34E;</div>
<div class="promo-card__value">100<span class="promo-card__unit">+</span></div>
<div class="promo-card__label">菜品任选</div>
</div>
<div class="promo-card">
<div class="promo-card__icon">&#x1F331;</div>
<div class="promo-card__value">5<span class="promo-card__unit"></span></div>
<div class="promo-card__label">营养素分析</div>
</div>
<div class="promo-card">
<div class="promo-card__icon">&#x1F4F1;</div>
<div class="promo-card__value">4<span class="promo-card__unit"></span></div>
<div class="promo-card__label">便捷支付</div>
</div>
<div class="promo-card">
<div class="promo-card__icon">&#x1F4CA;</div>
<div class="promo-card__value">7×24<span class="promo-card__unit"></span></div>
<div class="promo-card__label">营养监测</div>
</div>
</div>
<!-- 底部提示 -->
<div class="footer-tip">
<span class="footer-tip__dot"></span>
<span>请从左侧取餐区取餐后,前往结算台完成支付</span>
</div>
</div>
<script>
function updateClock() {
var now = new Date();
var hh = String(now.getHours()).padStart(2, '0');
var mm = String(now.getMinutes()).padStart(2, '0');
var ss = String(now.getSeconds()).padStart(2, '0');
document.getElementById('bigTime').textContent = hh + ':' + mm + ':' + ss;
var year = now.getFullYear();
var month = String(now.getMonth() + 1).padStart(2, '0');
var date = String(now.getDate()).padStart(2, '0');
var weekDay = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][now.getDay()];
document.getElementById('bigDate').firstChild.textContent = ' ' + year + ' 年 ' + month + ' 月 ' + date + ' 日 · ' + weekDay + ' ';
/* 自动判断餐次 */
var hour = now.getHours();
var mealTag = document.getElementById('mealTag');
if (hour >= 6 && hour < 10) {
mealTag.style.background = 'rgba(250,140,22,0.25)';
mealTag.style.color = '#fb923c';
mealTag.style.borderColor = 'rgba(250,140,22,0.5)';
mealTag.innerHTML = '&#x1F305; 早餐时段';
} else if (hour >= 10 && hour < 14) {
mealTag.innerHTML = '&#x1F96A; 午餐时段';
} else if (hour >= 16 && hour < 21) {
mealTag.style.background = 'rgba(34,197,94,0.25)';
mealTag.style.color = '#4ade80';
mealTag.style.borderColor = 'rgba(34,197,94,0.5)';
mealTag.innerHTML = '&#x1F319; 晚餐时段';
} else {
mealTag.innerHTML = '&#x1F31F; 欢迎光临';
}
}
updateClock();
setInterval(updateClock, 1000);
</script>
</body>
</html>
@@ -0,0 +1,716 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: linear-gradient(180deg, #0e1326 0%, #1a2b4a 50%, #0e1326 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部标题区 */
.header {
padding: 20px 36px;
background: rgba(26, 43, 74, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
}
.header__title {
font-size: 22px;
font-weight: 700;
color: #fff;
display: flex;
align-items: center;
gap: 10px;
}
.header__count {
padding: 3px 12px;
background: rgba(74, 144, 217, 0.2);
border: 1px solid rgba(74, 144, 217, 0.4);
border-radius: 14px;
font-size: 13px;
color: #60a5fa;
}
.header__time {
font-size: 13px;
color: rgba(255, 255, 255, 0.55);
font-family: Menlo, Consolas, monospace;
}
/* 主体:左右两列 */
.body {
flex: 1;
display: grid;
grid-template-columns: 1fr 360px;
overflow: hidden;
}
/* 左:商品列表 */
.items-area {
padding: 14px 28px 18px;
overflow-y: auto;
scrollbar-width: none;
display: flex;
flex-direction: column;
}
.items-area::-webkit-scrollbar { display: none; }
.zone-header {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
font-weight: 600;
letter-spacing: 0.5px;
padding: 6px 0 8px;
border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
margin-bottom: 6px;
margin-top: 4px;
display: flex;
align-items: center;
gap: 8px;
}
.zone-header__count {
padding: 1px 8px;
background: rgba(74, 144, 217, 0.18);
border-radius: 10px;
font-size: 11px;
color: #60a5fa;
font-weight: 500;
}
.item-card {
display: grid;
grid-template-columns: 24px auto 1fr auto;
gap: 10px;
padding: 8px 14px;
background: rgba(26, 43, 74, 0.35);
border: 1px solid rgba(255, 255, 255, 0.04);
border-radius: 8px;
margin-bottom: 4px;
align-items: center;
animation: slideIn 0.4s ease;
}
@keyframes slideIn {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}
.item-card__seq {
width: 22px;
height: 22px;
border-radius: 50%;
background: rgba(74, 144, 217, 0.18);
border: 1px solid rgba(74, 144, 217, 0.35);
color: #60a5fa;
font-size: 11px;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.item-card__info {
display: flex;
align-items: baseline;
gap: 8px;
min-width: 0;
}
.item-card__name {
font-size: 15px;
color: #fff;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-card__unit-price {
font-size: 12px;
color: rgba(255, 255, 255, 0.55);
font-family: Menlo, Consolas, monospace;
flex-shrink: 0;
}
.item-card__weight {
font-size: 12px;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
padding: 2px 10px;
background: rgba(10, 196, 168, 0.12);
border-radius: 10px;
white-space: nowrap;
text-align: center;
min-width: 76px;
justify-self: center;
}
.item-card__price {
font-size: 16px;
color: #0AC4A8;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
white-space: nowrap;
}
/* 列表底部统一小计条 */
.subtotal-bar {
margin-top: 10px;
padding: 12px 16px;
background: linear-gradient(90deg, rgba(10, 196, 168, 0.12), rgba(74, 144, 217, 0.08));
border: 1px solid rgba(10, 196, 168, 0.3);
border-radius: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
/* 表头 */
.table-head {
display: grid;
grid-template-columns: 24px auto 1fr auto;
gap: 10px;
padding: 6px 14px;
font-size: 11px;
color: rgba(255, 255, 255, 0.4);
letter-spacing: 1px;
font-weight: 500;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
margin-bottom: 4px;
}
.table-head__name { text-align: left; }
.table-head__weight { text-align: center; justify-self: center; }
.table-head__price { text-align: right; }
.subtotal-bar__count {
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
}
.subtotal-bar__count strong {
color: #fff;
font-size: 15px;
font-family: Menlo, Consolas, monospace;
margin: 0 2px;
}
.subtotal-bar__amount {
font-size: 22px;
font-weight: 700;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
}
/* 右:用户 + 金额 + 营养 */
.side-area {
padding: 16px 20px;
background: rgba(26, 43, 74, 0.3);
border-left: 1px solid rgba(255, 255, 255, 0.06);
display: flex;
flex-direction: column;
gap: 14px;
overflow: hidden;
}
/* 用户信息卡 */
.user-card {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 14px;
background: linear-gradient(90deg, rgba(74, 144, 217, 0.15), rgba(10, 196, 168, 0.06));
border: 1px solid rgba(74, 144, 217, 0.3);
border-radius: 12px;
}
.user-card__avatar {
width: 44px;
height: 44px;
border-radius: 50%;
background: linear-gradient(135deg, #4a90d9, #0AC4A8);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
flex-shrink: 0;
box-shadow: 0 4px 12px rgba(74, 144, 217, 0.3);
}
.user-card__main {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 3px;
}
.user-card__name-row {
display: flex;
align-items: baseline;
gap: 8px;
}
.user-card__name {
font-size: 16px;
color: #fff;
font-weight: 700;
}
.user-card__empno {
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
font-family: Menlo, Consolas, monospace;
}
.user-card__sub {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
}
.user-card__level {
padding: 4px 10px;
background: linear-gradient(135deg, rgba(251, 191, 36, 0.25), rgba(251, 146, 60, 0.18));
border: 1px solid rgba(251, 191, 36, 0.5);
border-radius: 12px;
font-size: 11px;
color: #fbbf24;
font-weight: 700;
text-align: center;
line-height: 1.3;
flex-shrink: 0;
}
.user-card__level small {
display: block;
font-size: 9px;
color: rgba(251, 191, 36, 0.85);
font-weight: 500;
margin-top: 1px;
}
.section-label {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
letter-spacing: 1px;
display: flex;
align-items: center;
gap: 6px;
}
.section-label::before {
content: "";
width: 3px;
height: 11px;
background: #4a90d9;
border-radius: 2px;
}
/* 营养达标卡片 */
.nutrition-card {
flex: 1;
background: linear-gradient(135deg, rgba(10, 196, 168, 0.12), rgba(74, 144, 217, 0.06));
border: 1px solid rgba(10, 196, 168, 0.25);
border-radius: 12px;
padding: 12px 14px;
display: flex;
flex-direction: column;
}
.nutrition-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.nutrition-head__title {
font-size: 13px;
color: #fff;
font-weight: 600;
display: flex;
flex-direction: column;
gap: 2px;
}
.nutrition-head__title small {
font-size: 10px;
color: rgba(255, 255, 255, 0.5);
font-weight: 400;
}
.nutrition-score {
padding: 3px 10px;
background: rgba(251, 191, 36, 0.2);
border: 1px solid rgba(251, 191, 36, 0.4);
border-radius: 12px;
font-size: 12px;
color: #fbbf24;
font-weight: 700;
text-align: right;
}
.nutrition-score small {
display: block;
font-size: 10px;
color: rgba(251, 191, 36, 0.85);
font-weight: 500;
margin-top: 1px;
}
/* 热量环形 + 三大营养条 */
.nutrition-main {
display: grid;
grid-template-columns: 88px 1fr;
gap: 12px;
align-items: center;
}
.calorie-ring {
position: relative;
width: 88px;
height: 88px;
}
.calorie-ring__svg {
width: 100%;
height: 100%;
transform: rotate(-90deg);
}
.calorie-ring__center {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.calorie-ring__value {
font-size: 18px;
font-weight: 800;
color: #fff;
font-family: Menlo, Consolas, monospace;
line-height: 1;
}
.calorie-ring__unit {
font-size: 9px;
color: rgba(255, 255, 255, 0.5);
margin-top: 1px;
}
.calorie-ring__hint {
font-size: 9px;
color: #fbbf24;
margin-top: 3px;
font-weight: 600;
}
/* 三大营养素横条 */
.macro-list {
display: flex;
flex-direction: column;
gap: 7px;
}
.macro-row__head {
display: flex;
justify-content: space-between;
align-items: baseline;
font-size: 11px;
margin-bottom: 3px;
}
.macro-row__label {
color: rgba(255, 255, 255, 0.7);
display: flex;
align-items: center;
gap: 4px;
}
.macro-row__dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.macro-row__value {
color: #fff;
font-family: Menlo, Consolas, monospace;
font-weight: 600;
}
.macro-row__value small {
color: rgba(255, 255, 255, 0.4);
font-weight: 400;
font-size: 10px;
margin-left: 2px;
}
.macro-bar {
position: relative;
height: 6px;
background: rgba(0, 0, 0, 0.3);
border-radius: 3px;
}
.macro-bar__target {
position: absolute;
top: -2px;
bottom: -2px;
width: 2px;
background: rgba(255, 255, 255, 0.6);
border-radius: 1px;
}
.macro-bar__fill {
position: absolute;
top: 0;
bottom: 0;
left: 0;
border-radius: 3px;
}
/* 营养结论 */
.nutrition-conclusion {
margin-top: 10px;
padding: 7px 10px;
background: rgba(251, 191, 36, 0.1);
border-left: 2px solid #fbbf24;
border-radius: 4px;
font-size: 11px;
color: rgba(255, 255, 255, 0.78);
line-height: 1.5;
}
/* 应付金额(突出展示) */
.amount-card {
background: linear-gradient(135deg, rgba(10, 196, 168, 0.18), rgba(0, 0, 0, 0.35));
border: 1.5px solid rgba(10, 196, 168, 0.55);
border-radius: 14px;
padding: 14px 16px;
text-align: center;
box-shadow: 0 6px 20px rgba(10, 196, 168, 0.18);
}
.amount-card__label {
font-size: 14px;
color: rgba(255, 255, 255, 0.85);
font-weight: 600;
letter-spacing: 1px;
margin-bottom: 4px;
}
.amount-card__value {
font-size: 52px;
font-weight: 800;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
line-height: 1.05;
text-shadow: 0 0 24px rgba(10, 196, 168, 0.4);
}
.amount-card__sub {
font-size: 12px;
color: rgba(255, 255, 255, 0.55);
margin-top: 4px;
}
.amount-card__sub strong { color: #4ade80; }
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部标题 -->
<div class="header">
<div class="header__title">
&#x1F6CD;&#xFE0F; 您的取餐明细
<span class="header__count">共 5 件</span>
</div>
<div class="header__time" id="nowTime">2026-08-06 12:30:45</div>
</div>
<!-- 主体 -->
<div class="body">
<!-- 左:商品列表 -->
<div class="items-area">
<!-- 表头 -->
<div class="table-head">
<span>#</span>
<span class="table-head__name">餐品名称 / 单价</span>
<span class="table-head__weight">取餐量</span>
<span class="table-head__price">金额</span>
</div>
<!-- 餐线 -->
<div class="zone-header">
<span>&#x1F95C; 餐线菜品</span>
<span class="zone-header__count">2 件</span>
</div>
<div class="item-card">
<div class="item-card__seq">1</div>
<div class="item-card__info">
<span class="item-card__name">清炒时蔬</span>
<span class="item-card__unit-price">¥4.00/100g</span>
</div>
<span class="item-card__weight">取 150g</span>
<div class="item-card__price">¥6.00</div>
</div>
<div class="item-card">
<div class="item-card__seq">2</div>
<div class="item-card__info">
<span class="item-card__name">米饭</span>
<span class="item-card__unit-price">¥1.60/100g</span>
</div>
<span class="item-card__weight">取 250g</span>
<div class="item-card__price">¥4.00</div>
</div>
<!-- 档口 -->
<div class="zone-header">
<span>&#x2696;&#xFE0F; 档口菜品</span>
<span class="zone-header__count">3 件</span>
</div>
<div class="item-card">
<div class="item-card__seq">3</div>
<div class="item-card__info">
<span class="item-card__name">红烧肉</span>
<span class="item-card__unit-price">¥12.00/100g</span>
</div>
<span class="item-card__weight">取 180g</span>
<div class="item-card__price">¥21.60</div>
</div>
<div class="item-card">
<div class="item-card__seq">4</div>
<div class="item-card__info">
<span class="item-card__name">鱼香肉丝</span>
<span class="item-card__unit-price">¥7.50/100g</span>
</div>
<span class="item-card__weight">取 160g</span>
<div class="item-card__price">¥12.00</div>
</div>
<div class="item-card">
<div class="item-card__seq">5</div>
<div class="item-card__info">
<span class="item-card__name">冬瓜排骨汤</span>
<span class="item-card__unit-price">¥1.00/100g</span>
</div>
<span class="item-card__weight">取 300g</span>
<div class="item-card__price">¥3.00</div>
</div>
<!-- 统一小计条 -->
<div class="subtotal-bar">
<div class="subtotal-bar__count">餐品种类 <strong>5</strong> 项 · 总重量 <strong>1040</strong>g · 餐线 <strong>2</strong> · 档口 <strong>3</strong></div>
<div class="subtotal-bar__amount">¥46.60</div>
</div>
</div>
<!-- 右:用户信息 + 应付金额 + 营养达标 -->
<div class="side-area">
<!-- 用户信息卡 -->
<div class="user-card">
<div class="user-card__avatar">&#x1F464;&#x200D;&#x1F33E;</div>
<div class="user-card__main">
<div class="user-card__name-row">
<span class="user-card__name">张*明</span>
<span class="user-card__empno">EMP002346</span>
</div>
<span class="user-card__sub">研发中心 · 二荤餐线</span>
</div>
<div class="user-card__level">
金牌会员
<small>LV5</small>
</div>
</div>
<!-- 应付金额(突出) -->
<div class="amount-card">
<div class="amount-card__label">应付金额</div>
<div class="amount-card__value">¥41.60</div>
<div class="amount-card__sub">原价 <strong>¥46.60</strong> · 优惠金额 ¥5.00</div>
</div>
<!-- 营养达标分析 -->
<div class="nutrition-card">
<div class="nutrition-head">
<span class="nutrition-head__title">
&#x1F957; 本餐营养摄入
<small>您的午餐目标 · 热量 950 kcal</small>
</span>
<span class="nutrition-score">
&#x2B50; 88 分
<small>搭配均衡</small>
</span>
</div>
<div class="nutrition-main">
<!-- 热量环形(76%) -->
<div class="calorie-ring">
<svg class="calorie-ring__svg" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="42" fill="none" stroke="rgba(255,255,255,0.08)" stroke-width="8"/>
<circle cx="50" cy="50" r="42" fill="none" stroke="#0AC4A8" stroke-width="8"
stroke-linecap="round"
stroke-dasharray="263.9"
stroke-dashoffset="63.3"/>
</svg>
<div class="calorie-ring__center">
<div class="calorie-ring__value">720</div>
<div class="calorie-ring__unit">/ 950 kcal</div>
<div class="calorie-ring__hint">略少 76%</div>
</div>
</div>
<!-- 三大营养素 -->
<div class="macro-list">
<!-- 蛋白质:目标 35g · 实际 35g · 100% -->
<div class="macro-row">
<div class="macro-row__head">
<span class="macro-row__label"><span class="macro-row__dot" style="background:#4ade80;"></span>蛋白质</span>
<span class="macro-row__value">35<small>/ 35g</small></span>
</div>
<div class="macro-bar">
<div class="macro-bar__target" style="left:100%;"></div>
<div class="macro-bar__fill" style="width:100%;background:#4ade80;"></div>
</div>
</div>
<!-- 脂肪:目标 30g · 实际 28g · 93% -->
<div class="macro-row">
<div class="macro-row__head">
<span class="macro-row__label"><span class="macro-row__dot" style="background:#fbbf24;"></span>脂肪</span>
<span class="macro-row__value">28<small>/ 30g</small></span>
</div>
<div class="macro-bar">
<div class="macro-bar__target" style="left:100%;"></div>
<div class="macro-bar__fill" style="width:93%;background:#fbbf24;"></div>
</div>
</div>
<!-- 碳水:目标 110g · 实际 88g · 80% -->
<div class="macro-row">
<div class="macro-row__head">
<span class="macro-row__label"><span class="macro-row__dot" style="background:#60a5fa;"></span>碳水</span>
<span class="macro-row__value">88<small>/ 110g</small></span>
</div>
<div class="macro-bar">
<div class="macro-bar__target" style="left:100%;"></div>
<div class="macro-bar__fill" style="width:80%;background:#60a5fa;"></div>
</div>
</div>
</div>
</div>
<div class="nutrition-conclusion">
&#x1F4A1; 搭配均衡,蛋白质达标、脂肪与碳水略低于目标,建议搭配一份水果补充能量
</div>
</div>
</div>
</div>
</div>
<script>
function updateTime() {
var d = new Date();
var yyyy = d.getFullYear();
var mm = String(d.getMonth() + 1).padStart(2, '0');
var dd = String(d.getDate()).padStart(2, '0');
var hh = String(d.getHours()).padStart(2, '0');
var mi = String(d.getMinutes()).padStart(2, '0');
var ss = String(d.getSeconds()).padStart(2, '0');
document.getElementById('nowTime').textContent = yyyy + '-' + mm + '-' + dd + ' ' + hh + ':' + mi + ':' + ss;
}
updateTime();
setInterval(updateTime, 1000);
</script>
</body>
</html>
@@ -0,0 +1,210 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: linear-gradient(180deg, #0e1326 0%, #1a2b4a 50%, #0e1326 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
position: relative;
display: flex;
flex-direction: column;
}
/* 顶部金额条 */
.header {
padding: 24px 36px 20px;
background: rgba(26, 43, 74, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
}
.header__left { display: flex; align-items: baseline; gap: 12px; }
.header__label {
font-size: 14px;
color: rgba(255, 255, 255, 0.55);
}
.header__amount {
font-size: 42px;
font-weight: 700;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
line-height: 1;
}
.header__right {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: rgba(74, 144, 217, 0.15);
border: 1px solid rgba(74, 144, 217, 0.35);
border-radius: 18px;
font-size: 13px;
color: #60a5fa;
font-weight: 600;
}
.header__right__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #52c41a;
box-shadow: 0 0 8px #52c41a;
animation: pulse 1.2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(1.3); }
}
/* 主体 */
.body {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 30px 60px;
overflow: hidden;
}
/* 支付方式面板 */
.pay-panel {
width: 100%;
max-width: 720px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
}
/* 支付图标动画区 */
.pay-icon-area {
width: 200px;
height: 200px;
border-radius: 50%;
background: radial-gradient(circle at 50% 50%, rgba(74, 144, 217, 0.25), rgba(74, 144, 217, 0.05) 70%);
border: 2px solid rgba(74, 144, 217, 0.35);
display: flex;
align-items: center;
justify-content: center;
position: relative;
box-shadow: 0 0 60px rgba(74, 144, 217, 0.25);
}
/* 外圈呼吸 */
.pay-icon-area::before {
content: "";
position: absolute;
inset: -20px;
border-radius: 50%;
border: 1px solid rgba(74, 144, 217, 0.2);
animation: ripple 2s ease-out infinite;
}
.pay-icon-area::after {
content: "";
position: absolute;
inset: -40px;
border-radius: 50%;
border: 1px solid rgba(74, 144, 217, 0.1);
animation: ripple 2s ease-out infinite;
animation-delay: 0.7s;
}
@keyframes ripple {
0% { opacity: 1; transform: scale(0.8); }
100% { opacity: 0; transform: scale(1.2); }
}
.pay-icon-area__icon {
font-size: 100px;
filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.3));
}
/* 支付状态文字 */
.pay-status { display: flex; flex-direction: column; gap: 10px; }
.pay-status__title {
font-size: 36px;
font-weight: 700;
color: #fff;
letter-spacing: 2px;
}
.pay-status__hint {
font-size: 16px;
color: rgba(255, 255, 255, 0.65);
line-height: 1.6;
}
/* 额度提示(在线支付/餐券) */
.pay-method-tip {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 18px;
background: rgba(82, 196, 26, 0.1);
border: 1px solid rgba(82, 196, 26, 0.3);
border-radius: 22px;
font-size: 13px;
color: #4ade80;
}
</style>
</head>
<body>
<div class="device-frame">
<!-- 顶部金额条 -->
<div class="header">
<div class="header__left">
<span class="header__label">应付金额</span>
<span class="header__amount">¥41.60</span>
</div>
<div class="header__right">
<span class="header__right__dot"></span>
<span>等待支付中</span>
</div>
</div>
<!-- 主体 -->
<div class="body">
<!-- 当前支付方式:在线支付(扫码) -->
<div class="pay-panel" id="payPanel">
<div class="pay-icon-area">
<span class="pay-icon-area__icon" id="payIcon">&#x1F4F1;</span>
</div>
<div class="pay-status">
<div class="pay-status__title" id="payTitle">请出示付款码</div>
<div class="pay-status__hint" id="payHint">
打开微信/支付宝,将付款码对准扫码器
</div>
</div>
<div class="pay-method-tip" id="payTip">
&#x1F4F1; 支持微信 / 支付宝 / 银联云闪付
</div>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,565 @@
<!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;
}
.device-frame {
width: 1280px;
height: 720px;
background: linear-gradient(180deg, #0a2e1f 0%, #0e1326 50%, #0a2e1f 100%);
border-radius: 24px;
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(82, 196, 26, 0.15);
position: relative;
display: flex;
flex-direction: column;
}
/* 背景烟花动画 */
.confetti {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.confetti__piece {
position: absolute;
width: 8px;
height: 8px;
opacity: 0.7;
animation: fall 3s linear infinite;
}
@keyframes fall {
0% { transform: translateY(-100px) rotate(0deg); opacity: 1; }
100% { transform: translateY(800px) rotate(720deg); opacity: 0; }
}
/* 主体 */
.body {
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
align-items: center;
padding: 40px 50px;
gap: 30px;
z-index: 2;
overflow: hidden;
}
/* 左:成功动画 + 金额 */
.success-block {
display: flex;
flex-direction: column;
align-items: center;
gap: 18px;
}
.success-icon {
width: 140px;
height: 140px;
border-radius: 50%;
background: linear-gradient(135deg, #52c41a, #0AC4A8);
display: flex;
align-items: center;
justify-content: center;
font-size: 76px;
color: #fff;
box-shadow: 0 12px 50px rgba(82, 196, 26, 0.5), 0 0 0 12px rgba(82, 196, 26, 0.1);
animation: bounceIn 0.7s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
@keyframes bounceIn {
0% { transform: scale(0) rotate(-180deg); opacity: 0; }
60% { transform: scale(1.15) rotate(10deg); opacity: 1; }
100% { transform: scale(1) rotate(0); }
}
.success-title {
font-size: 40px;
font-weight: 700;
color: #fff;
letter-spacing: 4px;
text-align: center;
}
.success-amount {
text-align: center;
}
.success-amount__value {
font-size: 72px;
font-weight: 700;
color: #0AC4A8;
font-family: Menlo, Consolas, monospace;
line-height: 1;
text-shadow: 0 4px 24px rgba(10, 196, 168, 0.4);
}
.success-amount__method {
margin-top: 10px;
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 16px;
background: rgba(82, 196, 26, 0.2);
border: 1px solid rgba(82, 196, 26, 0.4);
border-radius: 18px;
font-size: 13px;
color: #4ade80;
}
/* 账户信息条(仅刷脸支付显示) */
.account-info {
width: 100%;
max-width: 360px;
padding: 12px 18px;
background: linear-gradient(90deg, rgba(74, 144, 217, 0.18), rgba(10, 196, 168, 0.12));
border: 1px solid rgba(74, 144, 217, 0.35);
border-radius: 12px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 14px;
animation: slideUp 0.5s ease;
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.account-info__col {
display: flex;
flex-direction: column;
gap: 2px;
}
.account-info__label {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
letter-spacing: 0.5px;
}
.account-info__value {
font-size: 18px;
font-weight: 700;
color: #fff;
font-family: Menlo, Consolas, monospace;
line-height: 1.1;
}
.account-info__value--expense { color: #fb923c; }
.account-info__value--balance { color: #4ade80; }
.account-info__divider {
width: 1px;
height: 32px;
background: rgba(255, 255, 255, 0.15);
}
/* 演示切换按钮(原型展示用) */
.demo-switcher {
position: absolute;
top: 16px;
right: 16px;
z-index: 10;
display: flex;
gap: 6px;
padding: 6px;
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 22px;
backdrop-filter: blur(8px);
}
.demo-switcher__btn {
padding: 5px 14px;
background: transparent;
border: none;
border-radius: 16px;
font-size: 12px;
color: rgba(255, 255, 255, 0.6);
cursor: pointer;
transition: all 0.25s;
font-family: inherit;
}
.demo-switcher__btn:hover {
color: #fff;
background: rgba(255, 255, 255, 0.06);
}
.demo-switcher__btn.active {
background: rgba(74, 144, 217, 0.35);
color: #fff;
box-shadow: 0 2px 8px rgba(74, 144, 217, 0.3);
}
/* 右:营养 + 引导 */
.side-block {
display: flex;
flex-direction: column;
gap: 18px;
}
/* 营养卡片 */
.nutrition-card {
background: linear-gradient(135deg, rgba(10, 196, 168, 0.15), rgba(74, 144, 217, 0.08));
border: 1px solid rgba(10, 196, 168, 0.3);
border-radius: 16px;
padding: 20px;
}
.nutrition-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 14px;
}
.nutrition-head__title {
font-size: 18px;
color: #fff;
font-weight: 600;
}
.nutrition-score {
display: flex;
flex-direction: column;
align-items: center;
padding: 6px 14px;
background: rgba(251, 191, 36, 0.15);
border: 1px solid rgba(251, 191, 36, 0.4);
border-radius: 12px;
}
.nutrition-score__label {
font-size: 10px;
color: rgba(251, 191, 36, 0.8);
letter-spacing: 1px;
}
.nutrition-score__value {
font-size: 22px;
color: #fbbf24;
font-weight: 700;
font-family: Menlo, Consolas, monospace;
}
.nutrition-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.nutrition-item {
text-align: center;
padding: 12px 4px;
background: rgba(0, 0, 0, 0.25);
border-radius: 8px;
}
.nutrition-item__label {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
margin-bottom: 4px;
}
.nutrition-item__value {
font-size: 22px;
font-weight: 700;
color: #fff;
font-family: Menlo, Consolas, monospace;
}
.nutrition-item__unit {
font-size: 10px;
color: rgba(255, 255, 255, 0.4);
font-weight: 400;
}
/* 健康建议 */
.health-tip {
padding: 14px 16px;
background: rgba(82, 196, 26, 0.1);
border: 1px solid rgba(82, 196, 26, 0.3);
border-radius: 12px;
font-size: 13px;
color: rgba(255, 255, 255, 0.85);
line-height: 1.6;
display: flex;
gap: 10px;
align-items: flex-start;
}
.health-tip__icon { font-size: 18px; }
.health-tip__text strong { color: #4ade80; }
/* 二维码引导 */
.qr-guide {
padding: 14px 18px;
background: rgba(26, 43, 74, 0.5);
border: 1px solid rgba(74, 144, 217, 0.3);
border-radius: 12px;
display: flex;
align-items: center;
gap: 14px;
}
.qr-guide__img {
width: 64px;
height: 64px;
border-radius: 8px;
background: #fff;
padding: 4px;
flex-shrink: 0;
}
.qr-guide__text { flex: 1; }
.qr-guide__title {
font-size: 14px;
color: #fff;
font-weight: 600;
margin-bottom: 2px;
}
.qr-guide__sub {
font-size: 11px;
color: rgba(255, 255, 255, 0.55);
line-height: 1.5;
}
/* 底部 */
.footer {
padding: 14px 36px;
background: rgba(0, 0, 0, 0.3);
border-top: 1px solid rgba(255, 255, 255, 0.06);
text-align: center;
flex-shrink: 0;
z-index: 2;
}
.footer__tip {
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
.footer__sub {
font-size: 12px;
color: rgba(255, 255, 255, 0.4);
margin-top: 4px;
}
</style>
</head>
<body>
<div class="device-frame">
<!-- 演示切换按钮(原型展示用,实际部署可移除) -->
<div class="demo-switcher">
<button class="demo-switcher__btn" data-method="online">在线支付演示</button>
<button class="demo-switcher__btn active" data-method="face">刷脸支付演示</button>
</div>
<!-- 烟花动画背景 -->
<div class="confetti" id="confetti"></div>
<!-- 主体 -->
<div class="body">
<!-- 左:成功动画 + 金额 -->
<div class="success-block">
<div class="success-icon">&#x2714;</div>
<div class="success-title">支付成功</div>
<!-- 账户信息条(仅刷脸支付显示) -->
<div class="account-info" id="accountInfo">
<div class="account-info__col">
<span class="account-info__label">本次消费</span>
<span class="account-info__value account-info__value--expense">-¥41.60</span>
</div>
<div class="account-info__divider"></div>
<div class="account-info__col">
<span class="account-info__label">账户余额 · 张明</span>
<span class="account-info__value account-info__value--balance">¥128.40</span>
</div>
</div>
<div class="success-amount">
<div class="success-amount__value">¥41.60</div>
<div class="success-amount__method" id="payMethodBadge">&#x1F464; 刷脸支付 · 已扣款</div>
</div>
</div>
<!-- 右:营养 + 引导 -->
<div class="side-block">
<!-- 营养摘要 -->
<div class="nutrition-card">
<div class="nutrition-head">
<span class="nutrition-head__title">&#x1F957; 本餐营养摄入</span>
<div class="nutrition-score">
<span class="nutrition-score__label">SCORE</span>
<span class="nutrition-score__value">88</span>
</div>
</div>
<div class="nutrition-grid">
<div class="nutrition-item">
<div class="nutrition-item__label">热量</div>
<div class="nutrition-item__value">720<span class="nutrition-item__unit">kcal</span></div>
</div>
<div class="nutrition-item">
<div class="nutrition-item__label">蛋白质</div>
<div class="nutrition-item__value">35<span class="nutrition-item__unit">g</span></div>
</div>
<div class="nutrition-item">
<div class="nutrition-item__label">脂肪</div>
<div class="nutrition-item__value">28<span class="nutrition-item__unit">g</span></div>
</div>
<div class="nutrition-item">
<div class="nutrition-item__label">碳水</div>
<div class="nutrition-item__value">88<span class="nutrition-item__unit">g</span></div>
</div>
</div>
</div>
<!-- 健康建议 -->
<div class="health-tip">
<span class="health-tip__icon">&#x1F4A1;</span>
<span class="health-tip__text">
本餐蛋白质摄入 <strong>达标</strong>,建议下午补充 1500ml 水分,适量增加蔬菜摄入量
</span>
</div>
<!-- 小程序引导 -->
<div class="qr-guide">
<svg class="qr-guide__img" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="64" height="64" fill="#fff"/>
<g fill="#0e1326">
<!-- 三个定位角 -->
<rect x="4" y="4" width="14" height="14"/>
<rect x="6" y="6" width="10" height="10" fill="#fff"/>
<rect x="8" y="8" width="6" height="6" fill="#0e1326"/>
<rect x="46" y="4" width="14" height="14"/>
<rect x="48" y="6" width="10" height="10" fill="#fff"/>
<rect x="50" y="8" width="6" height="6" fill="#0e1326"/>
<rect x="4" y="46" width="14" height="14"/>
<rect x="6" y="48" width="10" height="10" fill="#fff"/>
<rect x="8" y="50" width="6" height="6" fill="#0e1326"/>
<!-- 数据点(模拟) -->
<rect x="22" y="6" width="2" height="2"/>
<rect x="26" y="6" width="2" height="2"/>
<rect x="30" y="6" width="2" height="2"/>
<rect x="38" y="6" width="2" height="2"/>
<rect x="22" y="10" width="2" height="2"/>
<rect x="34" y="10" width="2" height="2"/>
<rect x="22" y="14" width="6" height="2"/>
<rect x="32" y="14" width="2" height="2"/>
<rect x="38" y="14" width="2" height="2"/>
<rect x="6" y="22" width="2" height="2"/>
<rect x="10" y="22" width="2" height="2"/>
<rect x="14" y="22" width="2" height="2"/>
<rect x="22" y="22" width="2" height="2"/>
<rect x="26" y="22" width="6" height="2"/>
<rect x="34" y="22" width="2" height="2"/>
<rect x="42" y="22" width="2" height="2"/>
<rect x="50" y="22" width="2" height="2"/>
<rect x="54" y="22" width="2" height="2"/>
<rect x="6" y="26" width="2" height="2"/>
<rect x="14" y="26" width="2" height="2"/>
<rect x="22" y="26" width="2" height="2"/>
<rect x="30" y="26" width="2" height="2"/>
<rect x="38" y="26" width="2" height="2"/>
<rect x="46" y="26" width="2" height="2"/>
<rect x="54" y="26" width="2" height="2"/>
<rect x="10" y="30" width="2" height="2"/>
<rect x="18" y="30" width="2" height="2"/>
<rect x="26" y="30" width="2" height="2"/>
<rect x="34" y="30" width="2" height="2"/>
<rect x="42" y="30" width="2" height="2"/>
<rect x="50" y="30" width="2" height="2"/>
<rect x="58" y="30" width="2" height="2"/>
<rect x="6" y="34" width="2" height="2"/>
<rect x="14" y="34" width="2" height="2"/>
<rect x="22" y="34" width="2" height="2"/>
<rect x="30" y="34" width="6" height="2"/>
<rect x="42" y="34" width="2" height="2"/>
<rect x="50" y="34" width="2" height="2"/>
<rect x="22" y="38" width="2" height="2"/>
<rect x="26" y="38" width="2" height="2"/>
<rect x="34" y="38" width="2" height="2"/>
<rect x="42" y="38" width="2" height="2"/>
<rect x="46" y="38" width="2" height="2"/>
<rect x="54" y="38" width="2" height="2"/>
<rect x="22" y="42" width="6" height="2"/>
<rect x="34" y="42" width="2" height="2"/>
<rect x="42" y="42" width="2" height="2"/>
<rect x="50" y="42" width="6" height="2"/>
<rect x="22" y="46" width="2" height="2"/>
<rect x="30" y="46" width="2" height="2"/>
<rect x="22" y="50" width="2" height="2"/>
<rect x="26" y="50" width="2" height="2"/>
<rect x="34" y="50" width="2" height="2"/>
<rect x="42" y="50" width="2" height="2"/>
<rect x="46" y="50" width="2" height="2"/>
<rect x="54" y="50" width="2" height="2"/>
<rect x="22" y="54" width="2" height="2"/>
<rect x="30" y="54" width="2" height="2"/>
<rect x="38" y="54" width="2" height="2"/>
<rect x="46" y="54" width="2" height="2"/>
<rect x="50" y="54" width="6" height="2"/>
</g>
</svg>
<div class="qr-guide__text">
<div class="qr-guide__title">&#x1F4F1; 扫码查看详细营养报告</div>
<div class="qr-guide__sub">小程序内可查看每日营养摄入趋势、健康建议、餐品推荐</div>
</div>
</div>
</div>
</div>
<!-- 底部 -->
<div class="footer">
<div class="footer__tip">&#x1F60A; 感谢您的惠顾,祝您用餐愉快!</div>
<div class="footer__sub">合理膳食 · 均衡营养 · 健康生活</div>
</div>
</div>
<script>
/* 生成烟花碎片 */
function createConfetti() {
var colors = ['#52c41a', '#0AC4A8', '#4a90d9', '#fbbf24', '#fb923c', '#a855f7'];
var shapes = ['50%', '0', '0'];
var confetti = document.getElementById('confetti');
for (var i = 0; i < 40; i++) {
var piece = document.createElement('div');
piece.className = 'confetti__piece';
piece.style.left = Math.random() * 100 + '%';
piece.style.background = colors[Math.floor(Math.random() * colors.length)];
piece.style.borderRadius = shapes[Math.floor(Math.random() * shapes.length)];
piece.style.animationDelay = Math.random() * 3 + 's';
piece.style.animationDuration = (2 + Math.random() * 2) + 's';
piece.style.width = (6 + Math.random() * 8) + 'px';
piece.style.height = piece.style.width;
confetti.appendChild(piece);
}
}
createConfetti();
/* 支付方式演示切换 */
var methodConfig = {
online: {
badge: '&#x1F4F1; 在线支付 · 微信',
showAccount: false
},
face: {
badge: '&#x1F464; 刷脸支付 · 已扣款',
showAccount: true
}
};
function switchDemo(method) {
var cfg = methodConfig[method];
if (!cfg) return;
document.getElementById('payMethodBadge').innerHTML = cfg.badge;
document.getElementById('accountInfo').style.display = cfg.showAccount ? 'flex' : 'none';
document.querySelectorAll('.demo-switcher__btn').forEach(function(btn) {
btn.classList.toggle('active', btn.dataset.method === method);
});
}
document.querySelectorAll('.demo-switcher__btn').forEach(function(btn) {
btn.addEventListener('click', function() {
switchDemo(btn.dataset.method);
});
});
</script>
</body>
</html>