feat: 小程序就餐记录列表改造与拍照记录页新增,web-admin营养模块字段与终端设备列完善

- mini-program/eat-home.html: 今日就餐记录列表移除食物图标、加序号徽标、副信息改为重量/热量、新增就餐时间;数据来源扩展为员工食堂/补充记录/拍照记录三种;底部"自记餐品"按钮拆为"手动补录"+"拍照记录"双按钮
- mini-program/eat-photo-record.html: 新增拍照记录页,支持餐品名称输入+拍照/上传图片,可添加多个餐品并保存至 sessionStorage 与首页联动
- web-admin/nutrition: din-dish-add/din-dish-all 食材"是否主料"字段改为"食材类型"(主材/辅材/调料);prod-proc-combo/sup-in-cleanin/sup-in-raw/sup-pkg-label 新增"终端设备"列展示设备名与编号;din-recipe-mgmt 新增"同步至生产任务"按钮与"已同步"标签

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
fengpu
2026-06-22 17:01:08 +08:00
co-authored by Claude Opus 4.7
parent fbc9fdbddf
commit 7d7488737b
10 changed files with 523 additions and 108 deletions
@@ -1,5 +1,13 @@
# 营养管理小程序 CHANGELOG
## [1.3.0] - 2026-06-22
### 变更
**吃模块**
- `eat-home.html` — 今日就餐记录列表改造:移除食物图标,食物名称左上角新增序号徽标,食物名称下方副信息由「蛋白质/脂肪/碳水」改为「重量(g)· 热量(kcal)」;数据来源标识由两种扩展为三种(员工食堂 / 补充记录 / 拍照记录),其中拍照记录条目不显示重量与热量;底部「自记餐品」按钮拆分为「手动补录」+「拍照记录」两个按钮,分别跳转 `eat-self-record.html` 与新增页 `eat-photo-record.html`
- `eat-photo-record.html` — 新增拍照记录页:支持手动输入餐品名称 + 拍照/上传图片,可添加多个餐品并保存至 `sessionStorage['photoRecord_餐次']`,与 `eat-home.html` 就餐记录联动
## [1.2.1] - 2026-06-17
### 变更
+110 -53
View File
@@ -81,26 +81,37 @@
border-bottom: 0.5px solid #f5f5f5; cursor: pointer; text-decoration: none; color: inherit;
}
.meal-item:last-child { border-bottom: none; }
.meal-item .food-icon {
width: 44px; height: 44px; border-radius: 12px; background: #f5f5f5;
display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0;
}
.meal-item .food-info { flex: 1; min-width: 0; }
.meal-item .food-name { font-size: 14px; font-weight: 500; }
.meal-item .food-meta { font-size: 12px; color: #999; margin-top: 2px; }
/* 右侧:热量 + 来源徽标(员工食堂 / 自记餐品) */
.meal-item .food-right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; }
.meal-item .food-cal { font-size: 13px; font-weight: 600; color: #fa8c16; }
.meal-item .food-source { font-size: 10px; color: #999; padding: 1px 6px; border-radius: 3px; background: #f5f5f5; }
.meal-item .food-source.self { color: #1677ff; background: #e6f4ff; }
/* 自记餐品按钮(位于餐品列表下方) */
.self-record-btn-wrap { padding: 4px 16px 16px; background: #fff; }
.self-record-btn {
width: 100%; padding: 11px 0; border-radius: 12px; border: 1.5px dashed #1677ff;
background: #f0f7ff; color: #1677ff; font-size: 14px; font-weight: 600;
cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 4px;
/* 食物名称行:序号 + 名称 + 重量/热量(右对齐) */
.meal-item .food-name-row { display: flex; align-items: center; gap: 6px; }
.meal-item .food-index {
flex-shrink: 0; min-width: 18px; height: 18px; line-height: 18px; padding: 0 5px;
border-radius: 9px; background: #1677ff; color: #fff;
font-size: 11px; font-weight: 600; text-align: center;
}
.self-record-btn:active { background: #d6e8ff; }
.meal-item .food-name { font-size: 14px; font-weight: 500; flex-shrink: 0; }
.meal-item .food-meta { font-size: 12px; color: #999; text-align: right; }
/* 就餐时间 */
.meal-item .food-time { font-size: 11px; color: #bbb; margin-top: 4px; }
/* 右侧:来源徽标(员工食堂 / 补充记录 / 拍照记录) */
.meal-item .food-right { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; }
.meal-item .food-source {
font-size: 10px; color: #999; padding: 1px 6px; border-radius: 3px; background: #f5f5f5;
}
.meal-item .food-source.self { color: #1677ff; background: #e6f4ff; }
.meal-item .food-source.photo { color: #fa8c16; background: #fff7e6; }
/* 底部双按钮:手动补录 / 拍照记录 */
.record-actions-wrap { padding: 4px 16px 16px; background: #fff; }
.record-actions { display: flex; gap: 10px; }
.record-action-btn {
flex: 1; padding: 11px 0; border-radius: 12px;
font-size: 14px; font-weight: 600; cursor: pointer;
display: flex; align-items: center; justify-content: center; gap: 4px;
border: 1.5px dashed #1677ff; background: #f0f7ff; color: #1677ff;
}
.record-action-btn.photo { border-color: #fa8c16; background: #fff7e6; color: #fa8c16; }
.record-action-btn:active { opacity: 0.8; }
.record-action-btn .ra-icon { font-size: 16px; }
</style>
</head>
<body>
@@ -134,11 +145,16 @@
<div class="meal-tab">晚餐</div>
</div>
<div class="meal-list"></div>
<!-- 自记餐品按钮:跳转至自记餐品二级页面,按当前激活餐次 -->
<div class="self-record-btn-wrap">
<button class="self-record-btn" onclick="goSelfRecord()">
<span style="font-size:16px;"></span>自记餐品
</button>
<!-- 双按钮:手动补录 / 拍照记录 -->
<div class="record-actions-wrap">
<div class="record-actions">
<button class="record-action-btn" onclick="goSelfRecord()">
<span class="ra-icon">✏️</span>手动补录
</button>
<button class="record-action-btn photo" onclick="goPhotoRecord()">
<span class="ra-icon">📷</span>拍照记录
</button>
</div>
</div>
</div>
@@ -156,26 +172,27 @@
</div>
<script>
/* ========== 餐次菜品数据(来源:员工食堂) ========== */
/* meta 改为「重量 + 热量」格式,去除食物图标,新增就餐时间 */
var mealData = {
'早餐': [
{ icon: '🥛', name: '豆浆', meta: '蛋白质 3.6g · 碳水 8.2g', cal: '65kcal', source: '员工食堂' },
{ icon: '🥖', name: '油条', meta: '碳水 24g · 脂肪 12.8g', cal: '198kcal', source: '员工食堂' },
{ icon: '🥚', name: '水煮蛋', meta: '蛋白质 6.3g · 脂肪 5.3g', cal: '78kcal', source: '员工食堂' },
{ icon: '🥣', name: '小米粥', meta: '碳水 16g · 蛋白质 1.8g', cal: '72kcal', source: '员工食堂' }
{ name: '豆浆', weight: 250, cal: 65, source: '员工食堂', time: '2026-06-22 07:32:18' },
{ name: '油条', weight: 80, cal: 198, source: '员工食堂', time: '2026-06-22 07:32:42' },
{ name: '水煮蛋', weight: 50, cal: 78, source: '员工食堂', time: '2026-06-22 07:33:05' },
{ name: '小米粥', weight: 200, cal: 72, source: '员工食堂', time: '2026-06-22 07:33:28' }
],
'午餐': [
{ icon: '🍗', name: '宫保鸡丁', meta: '蛋白质 22.4g · 脂肪 14.2g', cal: '285kcal', source: '员工食堂' },
{ icon: '🐟', name: '清蒸鱼', meta: '蛋白质 20.8g · 脂肪 4.6g', cal: '142kcal', source: '员工食堂' },
{ icon: '🥦', name: '炒西兰花', meta: '蛋白质 3.2g · 脂肪 3.8g', cal: '68kcal', source: '员工食堂' },
{ icon: '🍚', name: '米饭(中碗)', meta: '碳水 58g · 蛋白质 4.2g', cal: '232kcal', source: '员工食堂' },
{ icon: '🥬', name: '蒜蓉油麦菜', meta: '蛋白质 1.8g · 脂肪 3.2g', cal: '52kcal', source: '员工食堂' },
{ icon: '🍲', name: '番茄蛋花汤', meta: '蛋白质 4.6g · 脂肪 2.1g', cal: '48kcal', source: '员工食堂' }
{ name: '宫保鸡丁', weight: 200, cal: 285, source: '员工食堂', time: '2026-06-22 12:08:15' },
{ name: '清蒸鱼', weight: 180, cal: 142, source: '员工食堂', time: '2026-06-22 12:08:38' },
{ name: '炒西兰花', weight: 150, cal: 68, source: '员工食堂', time: '2026-06-22 12:09:02' },
{ name: '米饭(中碗)', weight: 200, cal: 232, source: '员工食堂', time: '2026-06-22 12:09:25' },
{ name: '蒜蓉油麦菜', weight: 150, cal: 52, source: '员工食堂', time: '2026-06-22 12:09:48' },
{ name: '番茄蛋花汤', weight: 200, cal: 48, source: '员工食堂', time: '2026-06-22 12:10:12' }
],
'晚餐': [
{ icon: '🍳', name: '番茄炒蛋', meta: '蛋白质 10.2g · 脂肪 8.6g', cal: '156kcal', source: '员工食堂' },
{ icon: '🫑', name: '青椒肉丝', meta: '蛋白质 14.8g · 脂肪 9.2g', cal: '178kcal', source: '员工食堂' },
{ icon: '🥬', name: '紫菜蛋花汤', meta: '蛋白质 3.4g · 脂肪 1.2g', cal: '32kcal', source: '员工食堂' },
{ icon: '🍞', name: '馒头', meta: '碳水 44g · 蛋白质 7.0g', cal: '221kcal', source: '员工食堂' }
{ name: '番茄炒蛋', weight: 200, cal: 156, source: '员工食堂', time: '2026-06-22 18:15:33' },
{ name: '青椒肉丝', weight: 180, cal: 178, source: '员工食堂', time: '2026-06-22 18:15:58' },
{ name: '紫菜蛋花汤', weight: 200, cal: 32, source: '员工食堂', time: '2026-06-22 18:16:22' },
{ name: '馒头', weight: 100, cal: 221, source: '员工食堂', time: '2026-06-22 18:16:45' }
]
};
@@ -232,7 +249,15 @@
} catch (e) { return {}; }
}
/* 把某餐次的自记记录转为主列表渲染格式 */
/* 读取 sessionStorage 中某餐次的拍照记录 */
function loadPhotoRecord(mealType) {
try {
var raw = sessionStorage.getItem('photoRecord_' + mealType);
return raw ? JSON.parse(raw) : [];
} catch (e) { return []; }
}
/* 把某餐次的自记记录转为主列表渲染格式(补充记录来源) */
function computeSelfItems(mealType) {
var state = loadSelfRecord(mealType);
var items = [];
@@ -241,39 +266,66 @@
if (!rec || !rec.qty || rec.qty <= 0) return;
var d = findSelfDish(id);
if (!d) return;
var cal, qtyText;
var cal, gram;
if (rec.mode === '份') {
gram = d.gram * rec.qty;
cal = Math.round(d.cal * rec.qty);
qtyText = rec.qty + ' 份';
} else {
gram = rec.qty;
cal = Math.round(d.cal * rec.qty / d.gram);
qtyText = rec.qty + ' g';
}
items.push({
icon: d.icon, name: d.name,
meta: qtyText + ' · ' + d.desc,
cal: cal + 'kcal',
source: '自记餐品', isSelf: true
name: d.name,
weight: gram, cal: cal,
source: '补充记录', sourceClass: 'self',
time: rec.time || formatNow()
});
});
return items;
}
/* 把某餐次的拍照记录转为主列表渲染格式(拍照记录来源,无重量/热量) */
function computePhotoItems(mealType) {
return loadPhotoRecord(mealType).map(function(p) {
return {
name: p.name,
source: '拍照记录', sourceClass: 'photo',
skipMeta: true,
time: p.time || formatNow()
};
});
}
/* 格式化当前时间为「YYYY-MM-DD HH:mm:ss」 */
function formatNow() {
function pad(n) { return n < 10 ? '0' + n : '' + n; }
var d = new Date();
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate())
+ ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds());
}
/* ========== 主列表渲染 ========== */
var mealTabs = document.querySelectorAll('.meal-tab');
var mealList = document.querySelector('.meal-list');
function renderMeal(mealType) {
currentMeal = mealType;
var items = (mealData[mealType] || []).slice().concat(computeSelfItems(mealType));
mealList.innerHTML = items.map(function(d) {
var items = (mealData[mealType] || []).slice()
.concat(computeSelfItems(mealType))
.concat(computePhotoItems(mealType));
mealList.innerHTML = items.map(function(d, idx) {
/* 重量/热量放在餐品名后面(右对齐),拍照记录无此元素 */
var metaHtml = d.skipMeta ? '' :
'<span class="food-meta">重量 ' + d.weight + 'g · 热量 ' + d.cal + 'kcal</span>';
return '<a class="meal-item" href="eat-dish-detail.html">'
+ '<div class="food-icon">' + d.icon + '</div>'
+ '<div class="food-info"><div class="food-name">' + d.name + '</div>'
+ '<div class="food-meta">' + d.meta + '</div></div>'
+ '<div class="food-info">'
+ '<div class="food-name-row"><span class="food-index">' + (idx + 1) + '</span>'
+ '<span class="food-name">' + d.name + '</span></div>'
+ '<div class="food-time">' + (d.time || '') + '</div>'
+ '</div>'
+ '<div class="food-right">'
+ '<span class="food-cal">' + d.cal + '</span>'
+ '<span class="food-source' + (d.isSelf ? ' self' : '') + '">' + d.source + '</span>'
+ metaHtml
+ '<span class="food-source ' + (d.sourceClass || '') + '">' + d.source + '</span>'
+ '</div></a>';
}).join('');
}
@@ -286,11 +338,16 @@
});
});
/* 跳转到自记餐品二级页面,传当前餐次 */
/* 跳转到手动补录页(原自记餐品),传当前餐次 */
function goSelfRecord() {
location.href = 'eat-self-record.html?meal=' + encodeURIComponent(currentMeal);
}
/* 跳转到拍照记录页,传当前餐次 */
function goPhotoRecord() {
location.href = 'eat-photo-record.html?meal=' + encodeURIComponent(currentMeal);
}
/* 初始渲染:午餐 */
renderMeal('午餐');
</script>
@@ -0,0 +1,324 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拍照记录 | 智能餐养小程序</title>
<style>
/* 全局重置 */
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #2a2a2a; display: flex; justify-content: center; align-items: flex-start;
min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
padding: 24px 0 40px;
}
/* 手机壳 */
.phone-shell {
width: 390px; height: 844px; background: #fff; border-radius: 44px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3), inset 0 0 0 2px #e0e0e0;
overflow: hidden; position: relative; display: flex; flex-direction: column;
}
/* 状态栏 */
.status-bar {
height: 44px; background: #fff; display: flex; align-items: center;
justify-content: space-between; padding: 0 24px; font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.status-bar .time { font-size: 15px; font-weight: 700; }
.status-bar .icons { display: flex; gap: 6px; align-items: center; }
/* 导航栏 */
.nav-bar {
height: 44px; background: #fff; display: flex; align-items: center;
padding: 0 16px; border-bottom: 0.5px solid #f0f0f0; flex-shrink: 0; position: relative;
}
.nav-bar .back { font-size: 22px; color: #1677ff; cursor: pointer; text-decoration: none; line-height: 1; }
.nav-bar .title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 17px; font-weight: 600; }
.home-indicator {
height: 20px; display: flex; align-items: center; justify-content: center; background: #fff; flex-shrink: 0;
}
.home-indicator::after { content: ''; width: 120px; height: 5px; background: #1a1a1a; border-radius: 3px; opacity: 0.2; }
/* === 业务样式 === */
.page-body {
flex: 1; overflow-y: auto; background: #f5f5f5;
display: flex; flex-direction: column;
}
.page-body::-webkit-scrollbar { display: none; }
/* 当前餐次提示 */
.meal-tip {
padding: 10px 16px; background: #fff7e6; color: #fa8c16;
font-size: 12px; border-bottom: 0.5px solid #ffe7ba;
}
/* 添加区卡片 */
.add-card {
margin: 12px; background: #fff; border-radius: 12px; padding: 14px;
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.add-card .label {
font-size: 13px; color: #666; margin-bottom: 8px;
}
.name-input {
width: 100%; height: 38px; border: 1px solid #e0e0e0; border-radius: 8px;
padding: 0 12px; font-size: 14px; color: #333; outline: none;
background: #fafafa;
}
.name-input:focus { border-color: #fa8c16; background: #fff; }
.photo-row {
display: flex; gap: 10px; margin-top: 12px; align-items: center;
}
/* 拍照按钮 */
.photo-btn {
flex: 1; height: 80px; border: 1.5px dashed #fa8c16; border-radius: 10px;
background: #fff7e6; color: #fa8c16; font-size: 14px; font-weight: 600;
cursor: pointer; display: flex; flex-direction: column; align-items: center;
justify-content: center; gap: 4px;
}
.photo-btn .pb-icon { font-size: 26px; line-height: 1; }
.photo-btn:active { opacity: 0.8; }
.photo-btn input[type=file] { display: none; }
/* 添加到列表按钮 */
.add-list-btn {
width: 80px; height: 80px; border-radius: 10px;
background: #fa8c16; color: #fff; font-size: 13px; font-weight: 600;
cursor: pointer; border: none;
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
.add-list-btn:active { opacity: 0.85; }
.add-list-btn .al-icon { font-size: 22px; line-height: 1; }
/* 已添加餐品列表 */
.list-card {
flex: 1; margin: 0 12px 12px; background: #fff; border-radius: 12px;
padding: 4px 14px; box-shadow: 0 1px 3px rgba(0,0,0,0.04);
overflow-y: auto;
}
.list-card::-webkit-scrollbar { display: none; }
.list-card .lc-title {
font-size: 13px; color: #666; padding: 10px 0 6px;
border-bottom: 0.5px solid #f0f0f0;
}
.list-empty {
padding: 30px 0; text-align: center; color: #bbb; font-size: 13px;
}
/* 餐品条目 */
.dish-row {
display: flex; align-items: center; gap: 10px; padding: 10px 0;
border-bottom: 0.5px solid #f5f5f5;
}
.dish-row:last-child { border-bottom: none; }
.dish-row .dish-thumb {
width: 56px; height: 56px; border-radius: 8px; background: #f5f5f5;
background-size: cover; background-position: center; flex-shrink: 0;
display: flex; align-items: center; justify-content: center; font-size: 24px;
}
.dish-row .dish-info { flex: 1; min-width: 0; }
.dish-row .dish-name {
font-size: 14px; color: #333; font-weight: 500;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dish-row .dish-sub {
font-size: 11px; color: #fa8c16; margin-top: 3px;
}
.dish-row .del-btn {
width: 28px; height: 28px; border-radius: 50%; border: none;
background: #fff1f0; color: #ff4d4f; font-size: 16px; cursor: pointer;
flex-shrink: 0;
}
.dish-row .del-btn:active { opacity: 0.8; }
/* 底部保存栏 */
.save-bar {
padding: 10px 16px 14px; background: #fff; border-top: 0.5px solid #f0f0f0;
flex-shrink: 0;
}
.save-btn {
width: 100%; height: 44px; border-radius: 22px; border: none;
background: #fa8c16; color: #fff; font-size: 15px; font-weight: 600;
cursor: pointer;
}
.save-btn:active { opacity: 0.85; }
.save-btn:disabled { background: #ffd6a8; cursor: not-allowed; }
</style>
</head>
<body>
<div class="phone-shell">
<!-- 状态栏 -->
<div class="status-bar">
<span class="time">09:41</span>
<div class="icons">
<span>📶</span><span>WiFi</span><span>🔋</span>
</div>
</div>
<!-- 导航栏 -->
<div class="nav-bar">
<a class="back" href="eat-home.html"></a>
<span class="title">拍照记录</span>
</div>
<!-- 主体 -->
<div class="page-body">
<!-- 当前餐次提示 -->
<div class="meal-tip">当前餐次:<strong id="mealName">午餐</strong></div>
<!-- 添加区 -->
<div class="add-card">
<div class="label">餐品名称</div>
<input class="name-input" id="dishName" type="text" placeholder="请输入餐品名称" maxlength="20" />
<div class="photo-row">
<!-- 拍照/上传 -->
<label class="photo-btn">
<span class="pb-icon">📷</span>
<span id="photoBtnText">拍照 / 上传图片</span>
<input id="photoInput" type="file" accept="image/*" capture="environment" />
</label>
<!-- 添加到列表 -->
<button class="add-list-btn" onclick="addDish()">
<span class="al-icon"></span>
<span>添加</span>
</button>
</div>
</div>
<!-- 已添加餐品列表 -->
<div class="list-card">
<div class="lc-title">已添加餐品(<span id="dishCount">0</span></div>
<div id="dishList"></div>
</div>
</div>
<!-- 底部保存按钮 -->
<div class="save-bar">
<button class="save-btn" id="saveBtn" onclick="saveAll()">保存</button>
</div>
<!-- Home Indicator -->
<div class="home-indicator"></div>
</div>
<script>
/* ========== 解析当前餐次 ========== */
function getQueryMeal() {
var m = decodeURIComponent((location.search.match(/meal=([^&]+)/) || [,''])[1]);
return ['早餐','午餐','晚餐'].indexOf(m) >= 0 ? m : '午餐';
}
var currentMeal = getQueryMeal();
document.getElementById('mealName').textContent = currentMeal;
/* ========== 已添加餐品列表(内存态,未保存前不持久化) ========== */
/* 每条:{ name, image(DataURL 缩略图) } */
var dishList = [];
/* 当前选中的图片(DataURL */
var pendingImage = null;
/* 格式化当前时间为「YYYY-MM-DD HH:mm:ss」 */
function formatNow() {
function pad(n) { return n < 10 ? '0' + n : '' + n; }
var d = new Date();
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate())
+ ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds());
}
/* 拍照/上传图片处理 */
document.getElementById('photoInput').addEventListener('change', function(e) {
var file = e.target.files && e.target.files[0];
if (!file) return;
/* 压缩为缩略图,避免 sessionStorage 撑爆 */
var reader = new FileReader();
reader.onload = function(ev) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
var maxW = 200;
var w = img.width, h = img.height;
if (w > maxW) { h = h * maxW / w; w = maxW; }
canvas.width = w; canvas.height = h;
canvas.getContext('2d').drawImage(img, 0, 0, w, h);
pendingImage = canvas.toDataURL('image/jpeg', 0.7);
document.getElementById('photoBtnText').textContent = '已选图片 ✓';
};
img.src = ev.target.result;
};
reader.readAsDataURL(file);
});
/* 添加餐品到列表 */
function addDish() {
var nameEl = document.getElementById('dishName');
var name = nameEl.value.trim();
if (!name) {
alert('请输入餐品名称');
nameEl.focus();
return;
}
if (!pendingImage) {
alert('请先拍照或上传一张图片');
return;
}
dishList.push({ name: name, image: pendingImage, time: formatNow() });
/* 重置输入 */
nameEl.value = '';
pendingImage = null;
document.getElementById('photoInput').value = '';
document.getElementById('photoBtnText').textContent = '拍照 / 上传图片';
renderList();
}
/* 删除餐品 */
function removeDish(idx) {
dishList.splice(idx, 1);
renderList();
}
/* 渲染列表 */
function renderList() {
var listEl = document.getElementById('dishList');
document.getElementById('dishCount').textContent = dishList.length;
var saveBtn = document.getElementById('saveBtn');
saveBtn.disabled = dishList.length === 0;
if (dishList.length === 0) {
listEl.innerHTML = '<div class="list-empty">暂无餐品,请输入名称并拍照后添加</div>';
return;
}
listEl.innerHTML = dishList.map(function(d, idx) {
return '<div class="dish-row">'
+ '<div class="dish-thumb" style="background-image:url(' + d.image + ')"></div>'
+ '<div class="dish-info">'
+ '<div class="dish-name">' + escapeHtml(d.name) + '</div>'
+ '<div class="dish-sub">拍照记录</div>'
+ '</div>'
+ '<button class="del-btn" onclick="removeDish(' + idx + ')">×</button>'
+ '</div>';
}).join('');
}
/* 简单转义,避免 name 中含 HTML 特殊字符 */
function escapeHtml(s) {
return s.replace(/[&<>"']/g, function(c) {
return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c];
});
}
/* 保存到 sessionStorage 并返回首页 */
function saveAll() {
if (dishList.length === 0) return;
try {
sessionStorage.setItem('photoRecord_' + currentMeal, JSON.stringify(dishList));
} catch (e) {
alert('保存失败:图片数据过大');
return;
}
location.href = 'eat-home.html';
}
/* 初始化 */
renderList();
</script>
</body>
</html>