fix: 移除所有份数列/份数标注 + 调料设置页重构对齐组配页风格

- 组配秤 & 包装秤:移除份数列、第X份/Y份标注、每份/每份用量字段
- 包装秤 index:移除标签预览按钮;02-labeling:净菜包新增打印按钮
- 04-seasoning-settings:下拉框改搜索框、油格改2×2金色信息格对齐组配页、弹窗统一体验

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zhangyan
2026-07-06 15:32:01 +08:00
co-authored by Claude Opus 4.6
parent 5d02e675ae
commit 0088235446
10 changed files with 306 additions and 337 deletions
@@ -64,14 +64,14 @@
/* 表格头 */
.item-table__head {
display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.2fr 0.3fr 0.3fr 44px 50px; gap: 6px;
display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.3fr 0.3fr 44px 50px; gap: 6px;
padding: 5px 14px; background: rgba(0,0,0,0.2); font-size: 10px; color: rgba(255,255,255,0.4); font-weight: 500;
}
.item-table__body { display: flex; flex-direction: column; }
/* 餐品净菜包主行 */
.item-parent-row {
display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.2fr 0.3fr 0.3fr 44px 50px; gap: 6px;
display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.3fr 0.3fr 44px 50px; gap: 6px;
padding: 6px 14px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center;
background: rgba(74,144,217,0.06);
}
@@ -265,7 +265,7 @@
/* 表格头 */
var tableHead = document.createElement('div');
tableHead.className = 'item-table__head';
tableHead.innerHTML = '<div>名称</div><div style="text-align:center">净菜/餐品</div><div style="text-align:center">包装规格</div><div style="text-align:center">份数</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div><div style="text-align:center">操作</div>';
tableHead.innerHTML = '<div>名称</div><div style="text-align:center">净菜/餐品</div><div style="text-align:center">包装规格</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div><div style="text-align:center">操作</div>';
taskCard.appendChild(tableHead);
/* 表格体:按单份拆分展示 */
@@ -278,30 +278,28 @@
: { text: '已打印', cls: 'status-tag--done' };
var ingWeight = pack.ingredients[0] ? pack.ingredients[0].weightPerPack : 0;
/* 按 packSize 拆分为单份行 */
/* 从包装规格中提取应称重量(如"500g"→500 */
/* 从包装规格中提取应称重量(如"500g"→500),按整包计算 */
var specMatch = pack.packSpec && pack.packSpec.match(/(\d+)g/);
var dueWeight = specMatch ? parseInt(specMatch[1]) : ingWeight;
var doneWeight = currentFilter === 'done' ? dueWeight : 0;
var perDue = specMatch ? parseInt(specMatch[1]) : ingWeight;
var totalDue = perDue * pack.packSize;
var totalWeighed = currentFilter === 'done' ? totalDue : (pack.weighed || 0);
var weightClass = currentFilter === 'done' ? 'parent-weight--done' : '';
for (var p = 0; p < pack.packSize; p++) {
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
var statusCell = '<div style="text-align:center"><span class="status-tag ' + packStatus.cls + '">' + packStatus.text + '</span></div>';
var actionCell = currentFilter === 'done'
? '<div style="text-align:center"><button style="font-size:10px;padding:2px 8px;background:rgba(74,144,217,0.15);border:1px solid rgba(74,144,217,0.3);border-radius:4px;color:#4a90d9;cursor:pointer;font-family:inherit;" onclick="event.stopPropagation();handleReprint(\'' + order.orderNo + '\',\'' + pack.packName + '\',' + (p + 1) + ')">重新打印</button></div>'
: '<div style="text-align:center;font-size:10px;color:rgba(255,255,255,0.2)">—</div>';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + ' <span style="font-size:10px;color:rgba(255,255,255,0.4)">第' + (p + 1) + '份/' + pack.packSize + '份</span></span></div>' +
'<div style="text-align:center;font-size:11px;color:' + (pack.type === '餐品净菜包' ? '#faad16' : '#4a90d9') + '">' + pack.type + '</div>' +
'<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.55)">' + (pack.packSpec || '—') + '</div>' +
'<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.55)">1</div>' +
'<div class="parent-weight parent-weight--done">' + dueWeight + ' g</div>' +
'<div class="parent-weight">' + doneWeight + ' g</div>' +
statusCell +
actionCell;
tableBody.appendChild(parentRow);
}
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
var statusCell = '<div style="text-align:center"><span class="status-tag ' + packStatus.cls + '">' + packStatus.text + '</span></div>';
var actionCell = currentFilter === 'done'
? '<div style="text-align:center"><button style="font-size:10px;padding:2px 8px;background:rgba(74,144,217,0.15);border:1px solid rgba(74,144,217,0.3);border-radius:4px;color:#4a90d9;cursor:pointer;font-family:inherit;" onclick="event.stopPropagation();handleReprint(\'' + order.orderNo + '\',\'' + pack.packName + '\')">重新打印</button></div>'
: '<div style="text-align:center;font-size:10px;color:rgba(255,255,255,0.2)">—</div>';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + '</span></div>' +
'<div style="text-align:center;font-size:11px;color:' + (pack.type === '餐品净菜包' ? '#faad16' : '#4a90d9') + '">' + pack.type + '</div>' +
'<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.55)">' + (pack.packSpec || '—') + '</div>' +
'<div class="parent-weight ' + weightClass + '">' + totalDue + ' g</div>' +
'<div class="parent-weight ' + weightClass + '">' + totalWeighed + ' g</div>' +
statusCell +
actionCell;
tableBody.appendChild(parentRow);
});
taskCard.appendChild(tableBody);
@@ -328,9 +326,9 @@
window.location.href = target;
}
/* 重新打印(单行) */
function handleReprint(orderNo, packName, portion) {
showToast('重新打印: ' + orderNo + ' ' + packName + ' 第' + portion + '份', 2000, 'success');
/* 重新打印 */
function handleReprint(orderNo, packName) {
showToast('重新打印: ' + orderNo + ' ' + packName, 2000, 'success');
}
/* 重新打印(整单) */
@@ -324,10 +324,6 @@
<div class="task-card__item-label">订单类型</div>
<div class="task-card__item-value" id="taskOrderType">--</div>
</div>
<div class="task-card__item">
<div class="task-card__item-label">份数</div>
<div class="task-card__item-value task-card__item-value--green" id="taskTotalItems">--</div>
</div>
<div class="task-card__item">
<div class="task-card__item-label">订单状态</div>
<div class="task-card__item-value" id="taskStatus">--</div>
@@ -407,28 +403,25 @@
var allItems = [];
var currentVegIdx = 0;
/* ---- 初始化:按 packSize 展开为单份 ---- */
/* ---- 初始化 ---- */
function init() {
var task = taskData[taskNo];
if (!task) { showToast('任务不存在', 2000, 'error'); return; }
/* 每个 item 按 packSize 展开为独立份数 */
/* 每个 item 一行(不按 packSize 拆分) */
allItems = [];
task.items.forEach(function(item) {
for (var p = 0; p < item.packSize; p++) {
allItems.push({
type: item.type,
packName: item.packName,
packSpec: item.packSpec,
cutSpec: item.cutSpec,
weightPerPack: item.weightPerPack,
portionIdx: p + 1,
portionTotal: item.packSize,
weighed: 0,
icon: item.icon,
labeled: false
});
}
allItems.push({
type: item.type,
packName: item.packName,
packSpec: item.packSpec,
cutSpec: item.cutSpec,
weightPerPack: item.weightPerPack,
packSize: item.packSize,
weighed: item.weighed || 0,
icon: item.icon,
labeled: false
});
});
currentVegIdx = -1;
@@ -444,7 +437,6 @@
var orderTypeLabel = task.orderType === 'internal' ? '内供订单' : '外售订单';
var orderTypeCls = task.orderType === 'internal' ? 'order-type-tag--internal' : 'order-type-tag--external';
orderTypeEl.innerHTML = '<span class="order-type-tag ' + orderTypeCls + '">' + orderTypeLabel + '</span>';
document.getElementById('taskTotalItems').textContent = allItems.length;
updateTaskStatus();
renderItemList();
@@ -497,21 +489,14 @@
var labelBtnCls = item.labeled ? 'label-btn label-btn--done' : 'label-btn';
var typeTagCls = isMeal ? 'item-row__type-tag--meal' : 'item-row__type-tag--veg';
/* 按钮逻辑:净菜包无手动打印按钮(秤重确认时自动打印),餐品净菜包手动打印 */
var actionHtml;
if (isMeal) {
actionHtml = '<button class="' + labelBtnCls + '" onclick="handleSpitLabel(' + idx + ')">' + labelBtnText + '</button>';
} else {
if (item.labeled) {
actionHtml = '<button class="' + labelBtnCls + '" onclick="handleSpitLabel(' + idx + ')">重新打印</button>';
} else {
actionHtml = '';
}
}
/* 净菜包和餐品净菜包都有打印按钮 */
var actionHtml = '<button class="' + labelBtnCls + '" onclick="handleSpitLabel(' + idx + ')">' + labelBtnText + '</button>';
var totalDue = item.weightPerPack * (item.packSize || 1);
row.innerHTML =
'<div class="item-card__header">' +
'<div class="item-row__name"><span class="item-row__name-icon">' + item.icon + '</span>' + item.packName + ' <span style="font-size:10px;color:rgba(255,255,255,0.4)">第' + item.portionIdx + '份/' + item.portionTotal + '份</span></div>' +
'<div class="item-row__name"><span class="item-row__name-icon">' + item.icon + '</span>' + item.packName + '</div>' +
'<span class="item-row__type-tag ' + typeTagCls + '">' + item.type + '</span>' +
'<div class="item-row__status">' + labeledTag + '</div>' +
'<div class="item-row__action">' + actionHtml + '</div>' +
@@ -521,7 +506,7 @@
'<div class="item-card__meta-item"><span class="item-card__meta-label">净菜类型:</span><span class="item-card__meta-value">' + (isMeal ? '—' : (item.cutSpec || '—')) + '</span></div>' +
'</div>' +
'<div class="item-card__data">' +
'<div class="item-card__data-item"><span class="item-card__data-label">应称重量:</span><span class="item-card__data-value">' + item.weightPerPack + 'g</span></div>' +
'<div class="item-card__data-item"><span class="item-card__data-label">应称重量:</span><span class="item-card__data-value">' + totalDue + 'g</span></div>' +
'<div class="item-card__data-item"><span class="item-card__data-label">已称重量:</span><span class="item-card__data-value ' + (item.labeled ? 'item-card__data-value--done' : 'item-card__data-value--zero') + '">' + item.weighed + 'g</span></div>' +
'</div>';
@@ -627,9 +612,9 @@
document.getElementById('scaleWeightValue').textContent = allItems[matchedIdx].weighed.toFixed(2);
document.getElementById('statusDot').className = 'status-dot status-dot--done';
document.getElementById('statusText').textContent = '秤重确认: ' + result.name + ' 第' + allItems[matchedIdx].portionIdx + '份 — ' + scaleWeight.toFixed(1) + 'g';
document.getElementById('statusText').textContent = '秤重确认: ' + result.name + ' — ' + scaleWeight.toFixed(1) + 'g';
showToast('秤重完成: ' + result.name + ' 第' + allItems[matchedIdx].portionIdx + '份 ' + scaleWeight.toFixed(1) + 'g', 2000, 'success');
showToast('秤重完成: ' + result.name + ' ' + scaleWeight.toFixed(1) + 'g', 2000, 'success');
renderItemList();
updateTaskStatus();
@@ -107,11 +107,11 @@
.task-card__status { margin-left: auto; }
/* 表格头(7列) */
.item-table__head { display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.25fr 0.4fr 0.4fr 50px; gap: 6px; padding: 5px 14px; background: rgba(0,0,0,0.2); font-size: 10px; color: rgba(255,255,255,0.4); font-weight: 500; }
.item-table__head { display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.4fr 0.4fr 50px; gap: 6px; padding: 5px 14px; background: rgba(0,0,0,0.2); font-size: 10px; color: rgba(255,255,255,0.4); font-weight: 500; }
.item-table__body { display: flex; flex-direction: column; }
/* 行 */
.item-parent-row { display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.25fr 0.4fr 0.4fr 50px; gap: 6px; padding: 6px 14px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center; background: rgba(74,144,217,0.06); }
.item-parent-row { display: grid; grid-template-columns: 1fr 0.5fr 0.45fr 0.4fr 0.4fr 50px; gap: 6px; padding: 6px 14px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center; background: rgba(74,144,217,0.06); }
.parent-name { display: flex; align-items: center; gap: 8px; }
.parent-icon { width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 14px; background: rgba(114,46,209,0.15); flex-shrink: 0; }
.parent-name__text { font-size: 12px; font-weight: 600; color: #fff; }
@@ -192,10 +192,6 @@
<div class="stat-chip__icon stat-chip__icon--blue">&#x1F4CB;</div>
<div><div class="stat-chip__value" id="statTotal">0</div><div class="stat-chip__label" id="statTotalLabel">今日包装订单数</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--green">&#x1F4E6;</div>
<div><div class="stat-chip__value" id="statPacks">0</div><div class="stat-chip__label">总份数</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--orange">&#x1F96C;</div>
<div><div class="stat-chip__value" id="statFoods">0</div><div class="stat-chip__label">净菜种类</div></div>
@@ -392,21 +388,18 @@
var total = records.length;
var totalWeight = 0;
var foodSet = {};
var totalPacks = 0;
records.forEach(function(order) {
order.mealPacks.forEach(function(pack) {
pack.ingredients.forEach(function(ing) {
totalWeight += ing.weighed;
foodSet[ing.name] = true;
});
totalPacks += pack.packSize;
});
});
document.getElementById('statTotal').textContent = total;
document.getElementById('statTotalLabel').textContent = totalLabel;
document.getElementById('statWeight').textContent = totalWeight;
document.getElementById('statFoods').textContent = Object.keys(foodSet).length;
document.getElementById('statPacks').textContent = totalPacks;
}
/* 搜索输入处理 */
@@ -489,7 +482,7 @@
/* 表格头 */
var tableHead = document.createElement('div');
tableHead.className = 'item-table__head';
tableHead.innerHTML = '<div>名称</div><div style="text-align:center">净菜/餐品</div><div style="text-align:center">包装规格</div><div style="text-align:center">份数</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div>';
tableHead.innerHTML = '<div>名称</div><div style="text-align:center">净菜/餐品</div><div style="text-align:center">包装规格</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div>';
taskCard.appendChild(tableHead);
/* 表格体 */
@@ -498,26 +491,23 @@
order.mealPacks.forEach(function(pack) {
var ingWeight = pack.ingredients[0] ? pack.ingredients[0].weightPerPack : 0;
/* 从包装规格中提取应称重量(如"500g"→500 */
/* 从包装规格中提取应称重量(如"500g"→500,按整包计算 */
var specMatch = pack.packSpec && pack.packSpec.match(/(\d+)g/);
var dueWeight = specMatch ? parseInt(specMatch[1]) : ingWeight;
var perDue = specMatch ? parseInt(specMatch[1]) : ingWeight;
var totalDue = perDue * pack.packSize;
/* 按单份拆分,每份一行 */
for (var p = 0; p < pack.packSize; p++) {
var statusCell = '<div style="text-align:center"><span class="status-tag status-tag--done">已打印</span></div>';
var statusCell = '<div style="text-align:center"><span class="status-tag status-tag--done">已打印</span></div>';
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + ' <span style="font-size:10px;color:rgba(255,255,255,0.4)">第' + (p + 1) + '份/' + pack.packSize + '份</span></span></div>' +
'<div style="text-align:center;font-size:11px;color:' + (pack.type === '餐品净菜包' ? '#faad16' : '#4a90d9') + '">' + pack.type + '</div>' +
'<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.55)">' + (pack.packSpec || '—') + '</div>' +
'<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.55)">1</div>' +
'<div class="parent-weight parent-weight--done">' + dueWeight + ' g</div>' +
'<div class="parent-weight parent-weight--done">' + dueWeight + ' g</div>' +
statusCell;
tableBody.appendChild(parentRow);
}
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + '</span></div>' +
'<div style="text-align:center;font-size:11px;color:' + (pack.type === '餐品净菜包' ? '#faad16' : '#4a90d9') + '">' + pack.type + '</div>' +
'<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.55)">' + (pack.packSpec || '—') + '</div>' +
'<div class="parent-weight parent-weight--done">' + totalDue + ' g</div>' +
'<div class="parent-weight parent-weight--done">' + totalDue + ' g</div>' +
statusCell;
tableBody.appendChild(parentRow);
});
taskCard.appendChild(tableBody);
@@ -537,8 +527,8 @@
}
/* 重新打印 */
function handleReprint(orderNo, packName, portion) {
showToast('重新打印: ' + orderNo + ' ' + packName + ' 第' + portion + '份', 2000);
function handleReprint(orderNo, packName) {
showToast('重新打印: ' + orderNo + ' ' + packName, 2000);
}
/* Toast */
@@ -1,5 +1,13 @@
# 净菜包装贴标秤 CHANGELOG
## 2026-07-06 | 移除份数列 + 打印按钮
### 修改
- `01-orders.html` — 移除"份数"列和行拆分逻辑,grid 8列→7列;重量计算改用 `perDue * packSize`
- `02-labeling.html` — 移除"份数"信息卡片和清单拆分;净菜包/餐品净菜包均新增打印按钮
- `03-history.html` — 移除"总份数"统计标签和行拆分逻辑,grid 7列→6列
- `index.html` — 移除「标签预览」菜单按钮
## 2026-06-26 | 术语统一"贴标→包装" + 包装作业交互升级
### 术语统一
@@ -98,15 +98,6 @@
</div>
<div class="menu-btn__arrow">&#x203A;</div>
</a>
<a class="menu-btn" onclick="handleMenu('label-preview.html')">
<div class="menu-btn__icon menu-btn__icon--green">&#x1F3F7;&#xFE0F;</div>
<div class="menu-btn__info">
<div class="menu-btn__title">标签预览</div>
<div class="menu-btn__desc">预览订单/净菜/餐品净菜包三种标签</div>
</div>
<div class="menu-btn__arrow">&#x203A;</div>
</a>
</div>
</div>
</div>
@@ -59,16 +59,16 @@
.task-card__pack-btn:hover { background: #5ba0e9; }
.task-card__pack-btn:disabled { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.4); cursor: not-allowed; }
/* 表格头(7列 */
/* 表格头(6列:名称/包装规格/应称重量/已称重量/状态/操作 */
.item-table__head {
display: grid; grid-template-columns: 1fr 0.55fr 0.35fr 0.55fr 0.55fr 46px 66px; gap: 6px;
display: grid; grid-template-columns: 1fr 0.65fr 0.55fr 0.55fr 46px 66px; gap: 6px;
padding: 6px 16px; background: rgba(0,0,0,0.2); font-size: 11px; color: rgba(255,255,255,0.4); font-weight: 500;
}
.item-table__body { display: flex; flex-direction: column; }
/* 餐品净菜包主行 */
.item-parent-row {
display: grid; grid-template-columns: 1fr 0.55fr 0.35fr 0.55fr 0.55fr 46px 66px; gap: 6px;
display: grid; grid-template-columns: 1fr 0.65fr 0.55fr 0.55fr 46px 66px; gap: 6px;
padding: 10px 16px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center;
background: rgba(74,144,217,0.06);
margin-bottom: 4px; border-radius: 6px;
@@ -298,10 +298,10 @@
'<span class="task-card__status"><span class="status-badge ' + (orderAllDone ? 'status-badge--done' : 'status-badge--pending') + '">' + (orderAllDone ? '已完成' : '待组配') + '</span></span>';
taskCard.appendChild(header);
/* 表格头(7列:名称/包装规格/份数/应称重量/已称重量/状态/操作) */
/* 表格头(6列:名称/包装规格/应称重量/已称重量/状态/操作) */
var tableHead = document.createElement('div');
tableHead.className = 'item-table__head';
tableHead.innerHTML = '<div>餐品净菜包名称</div><div style="text-align:center">包装规格</div><div style="text-align:center">份数</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div><div style="text-align:center">操作</div>';
tableHead.innerHTML = '<div>餐品净菜包名称</div><div style="text-align:center">包装规格</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div><div style="text-align:center">操作</div>';
taskCard.appendChild(tableHead);
/* 表格体 */
@@ -313,44 +313,32 @@
/* 主辅材合计 */
var ingNeed = 0, ingWeighed = 0;
pack.ingredients.forEach(function(ing) {
ingNeed += ing.weightPerPack * pack.packSize;
ingNeed += ing.weightPerPack;
ingWeighed += ing.weighed;
});
/* 调料合计 */
var seaNeed = 0, seaWeighed = 0;
if (pack.seasonings) {
pack.seasonings.forEach(function(sea) {
seaNeed += sea.weightPerPack * pack.packSize;
seaNeed += sea.weightPerPack;
seaWeighed += sea.weighed;
});
}
var totalNeed = Math.round((ingNeed + seaNeed) * 100) / 100;
var totalWeighed = Math.round((ingWeighed + seaWeighed) * 100) / 100;
var perPackWeight = Math.round((totalNeed / pack.packSize) * 100) / 100;
var perPackWeighed = Math.round((totalWeighed / pack.packSize) * 100) / 100;
var packDone = !hasPendingPack(pack);
/* 从包装规格中提取重量(如"大份800g"→800 */
var specMatch = pack.packSpec && pack.packSpec.match(/(\d+)g/);
var specWeight = specMatch ? parseInt(specMatch[1]) : perPackWeight;
/* 按单份拆分,每份一行 */
for (var p = 0; p < pack.packSize; p++) {
var portionWeighed = packDone ? perPackWeighed : 0;
var weightClass = packDone ? 'parent-weight--done' : '';
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + ' <span style="font-size:10px;color:rgba(255,255,255,0.4)">第' + (p + 1) + '份/' + pack.packSize + '份</span></span></div>' +
'<div style="text-align:center"><span class="pack-spec-tag">' + (pack.packSpec || '—') + '</span></div>' +
'<div style="text-align:center"><span class="pack-size-tag">1</span></div>' +
'<div class="parent-weight ' + weightClass + '">' + specWeight + ' 克</div>' +
'<div class="parent-weight ' + weightClass + '">' + portionWeighed + ' 克</div>' +
'<div style="text-align:center"><span class="status-tag ' + (packDone ? 'status-tag--done' : 'status-tag--wait') + '">' + (packDone ? '已完成' : '待组配') + '</span></div>' +
'<div style="text-align:center">' + (packDone ? '' : '<button class="task-card__pack-btn" onclick="handlePackWeigh(\'' + order.taskNo + '\',\'' + order.orderNo + '\',\'' + encodeURIComponent(pack.packName) + '\',' + (p + 1) + ')">组配</button>') + '</div>';
tableBody.appendChild(parentRow);
}
var weightClass = packDone ? 'parent-weight--done' : '';
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + '</span></div>' +
'<div style="text-align:center"><span class="pack-spec-tag">' + (pack.packSpec || '—') + '</span></div>' +
'<div class="parent-weight ' + weightClass + '">' + totalNeed + ' 克</div>' +
'<div class="parent-weight ' + weightClass + '">' + totalWeighed + ' 克</div>' +
'<div style="text-align:center"><span class="status-tag ' + (packDone ? 'status-tag--done' : 'status-tag--wait') + '">' + (packDone ? '已完成' : '待组配') + '</span></div>' +
'<div style="text-align:center">' + (packDone ? '' : '<button class="task-card__pack-btn" onclick="handlePackWeigh(\'' + order.taskNo + '\',\'' + order.orderNo + '\',\'' + encodeURIComponent(pack.packName) + '\')">组配</button>') + '</div>';
tableBody.appendChild(parentRow);
});
taskCard.appendChild(tableBody);
@@ -380,9 +368,8 @@
}
/* 进入餐品净菜包组配详情 */
function handlePackWeigh(taskNo, orderNo, packName, portion) {
function handlePackWeigh(taskNo, orderNo, packName) {
var target = '02-weighing-packing.html?task=' + taskNo + '&order=' + encodeURIComponent(orderNo) + '&pack=' + packName;
if (portion) target += '&portion=' + portion;
if (userName) target += '&user=' + encodeURIComponent(userName);
window.location.href = target;
}
@@ -478,10 +478,6 @@
<div class="task-card__item-label">餐品名称</div>
<div class="task-card__item-value task-card__item-value--purple" id="taskPackName">--</div>
</div>
<div class="task-card__item">
<div class="task-card__item-label">组配份数</div>
<div class="task-card__item-value task-card__item-value--green" id="taskTotalPacks">--</div>
</div>
<div class="task-card__item">
<div class="task-card__item-label">餐品组配状态</div>
<div class="task-card__item-value" id="taskStatus">--</div>
@@ -683,8 +679,7 @@
icon: ing.icon,
cutSpec: ing.cutSpec,
weightPerPack: ing.weightPerPack,
weighed: ing.weighed,
packSize: 1
weighed: ing.weighed
};
});
@@ -694,21 +689,20 @@
name: sea.name,
cellIdx: sea.cellIdx,
weightPerPack: sea.weightPerPack,
weighed: sea.weighed,
packSize: 1
weighed: sea.weighed
};
});
/* 找到第一个待称重的主辅材 */
currentIngIdx = 0;
for (var j = 0; j < allIngredients.length; j++) {
var need = allIngredients[j].weightPerPack * allIngredients[j].packSize;
var need = allIngredients[j].weightPerPack;
if (allIngredients[j].weighed < need) { currentIngIdx = j; break; }
}
/* 找到第一个待称重的调料 */
currentSeaIdx = -1;
for (var k = 0; k < allSeasonings.length; k++) {
var seaNeed = allSeasonings[k].weightPerPack * allSeasonings[k].packSize;
var seaNeed = allSeasonings[k].weightPerPack;
if (allSeasonings[k].weighed < seaNeed) { currentSeaIdx = k; break; }
}
@@ -719,14 +713,13 @@
var orderTypeCls = task.orderType === 'internal' ? 'order-type-tag--internal' : 'order-type-tag--external';
orderTypeEl.innerHTML = '<span class="order-type-tag ' + orderTypeCls + '">' + orderTypeLabel + '</span>';
document.getElementById('taskPackName').textContent = currentPack.packName + ' · ' + (currentPack.packSpec || '—');
document.getElementById('taskTotalPacks').textContent = '1';
/* 订单状态:主辅材+调料全部完成才算完成 */
var ingAllDone = allIngredients.every(function(ing) {
return ing.weighed >= ing.weightPerPack * ing.packSize;
return ing.weighed >= ing.weightPerPack;
});
var seaAllDone = allSeasonings.every(function(sea) {
return sea.weighed >= sea.weightPerPack * sea.packSize;
return sea.weighed >= sea.weightPerPack;
});
var allDone = ingAllDone && seaAllDone;
var statusEl = document.getElementById('taskStatus');
@@ -753,7 +746,7 @@
body.innerHTML = '';
allIngredients.forEach(function(ing, idx) {
var need = Math.round(ing.weightPerPack * ing.packSize * 100) / 100;
var need = Math.round(ing.weightPerPack * 100) / 100;
var isDone = ing.weighed >= need;
var row = document.createElement('div');
@@ -773,7 +766,6 @@
'<div class="item-row__status">' + statusTag + '</div>' +
'</div>' +
'<div class="item-card__data">' +
'<div class="item-card__data-item"><span class="item-card__data-label">每份</span><span class="item-card__data-value">' + ing.weightPerPack + 'g</span></div>' +
'<div class="item-card__data-item"><span class="item-card__data-label">应称</span><span class="item-card__data-value">' + need + 'g</span></div>' +
'<div class="item-card__data-item"><span class="item-card__data-label">已称</span><span class="item-card__data-value ' + actualClass + '">' + ing.weighed + 'g</span></div>' +
'<div class="item-card__data-item"><span class="item-card__data-label">净菜类型</span><span class="item-card__data-value">' + (ing.cutSpec || '—') + '</span></div>' +
@@ -793,7 +785,7 @@
var infoCell = document.createElement('div');
infoCell.className = 'seasoning-cell seasoning-cell--info';
if (oilSea) {
var oilNeed = Math.round(oilSea.weightPerPack * oilSea.packSize * 100) / 100;
var oilNeed = Math.round(oilSea.weightPerPack * 100) / 100;
var oilDone = oilSea.weighed >= oilNeed;
/* 待组配→脉冲高亮,已组配→绿色 */
if (oilDone) {
@@ -808,7 +800,6 @@
'<span class="sea-slot__status ' + oilStatusCls + '">' + oilStatusText + '</span>' +
'<div class="sea-name"><span class="sea-name-icon">' + (oilSea.icon || '&#x1F6E2;') + '</span>' + oilSea.name + '</div>' +
'<div class="sea-fields">' +
'<div class="sea-field"><span class="sea-field__label">每份用量</span><span class="sea-field__value">' + oilSea.weightPerPack + 'g</span></div>' +
'<div class="sea-field"><span class="sea-field__label">应称</span><span class="sea-field__value">' + oilNeed + 'g</span></div>' +
'<div class="sea-field"><span class="sea-field__label">已称</span><span class="sea-field__value ' + oilActualCls + '">' + oilSea.weighed + 'g</span></div>' +
'</div>';
@@ -838,7 +829,7 @@
if (neededSea) {
/* 状态1/2:该格调料在本餐品组配清单中 — 待组配或已组配 */
var seaNeed2 = Math.round(neededSea.weightPerPack * neededSea.packSize * 100) / 100;
var seaNeed2 = Math.round(neededSea.weightPerPack * 100) / 100;
var seaDone2 = neededSea.weighed >= seaNeed2;
cell.classList.add('seasoning-cell--occupied');
@@ -859,7 +850,6 @@
'<span class="sea-slot__status ' + statusCls + '">' + statusText + '</span>' +
'<div class="sea-slot__name"><span class="sea-slot__name-icon">' + (neededSea.icon || '&#x1F9C2;') + '</span>' + neededSea.name + '</div>' +
'<div class="sea-slot__fields">' +
'<div class="sea-slot__field"><span class="sea-slot__field-label">每份</span><span class="sea-slot__field-value">' + neededSea.weightPerPack + 'g</span></div>' +
'<div class="sea-slot__field"><span class="sea-slot__field-label">应称</span><span class="sea-slot__field-value">' + seaNeed2 + 'g</span></div>' +
'<div class="sea-slot__field"><span class="sea-slot__field-label">已称</span><span class="sea-slot__field-value ' + actualCls2 + '">' + neededSea.weighed + 'g</span></div>' +
'</div>';
@@ -873,7 +863,6 @@
'<span class="sea-slot__pos">' + pos + '</span>' +
'<div class="sea-slot__name"><span class="sea-slot__name-icon">' + cfgIcon + '</span>' + cfg.name + '</div>' +
'<div class="sea-slot__fields">' +
'<div class="sea-slot__field"><span class="sea-slot__field-label">每份</span><span class="sea-slot__field-value">--</span></div>' +
'<div class="sea-slot__field"><span class="sea-slot__field-label">应称</span><span class="sea-slot__field-value">--</span></div>' +
'<div class="sea-slot__field"><span class="sea-slot__field-label">已称</span><span class="sea-slot__field-value">--</span></div>' +
'</div>';
@@ -896,7 +885,7 @@
function confirmSeasoningDirect(idx) {
if (idx < 0 || idx >= allSeasonings.length) return;
var sea = allSeasonings[idx];
var seaNeed = Math.round(sea.weightPerPack * sea.packSize * 100) / 100;
var seaNeed = Math.round(sea.weightPerPack * 100) / 100;
if (sea.weighed >= seaNeed) {
showToast(sea.name + ' 已组配', 1500, 'success');
return;
@@ -913,7 +902,7 @@
/* 自动跳到下一个待称调料 */
currentSeaIdx = -1;
for (var s = 0; s < allSeasonings.length; s++) {
if (allSeasonings[s].weighed < allSeasonings[s].weightPerPack * allSeasonings[s].packSize) {
if (allSeasonings[s].weighed < allSeasonings[s].weightPerPack) {
currentSeaIdx = s; break;
}
}
@@ -1022,7 +1011,7 @@
var found = false;
for (var i = 0; i < allIngredients.length; i++) {
if (allIngredients[i].weighed < allIngredients[i].weightPerPack * allIngredients[i].packSize) {
if (allIngredients[i].weighed < allIngredients[i].weightPerPack) {
currentIngIdx = i; found = true; break;
}
}
@@ -1045,10 +1034,10 @@
/* 更新订单整体状态 */
function updateOverallStatus() {
var ingDone = allIngredients.every(function(ing) {
return ing.weighed >= ing.weightPerPack * ing.packSize;
return ing.weighed >= ing.weightPerPack;
});
var seaDone = allSeasonings.every(function(sea) {
return sea.weighed >= sea.weightPerPack * sea.packSize;
return sea.weighed >= sea.weightPerPack;
});
var allDoneNow = ingDone && seaDone;
var taskStatusEl = document.getElementById('taskStatus');
@@ -1059,10 +1048,10 @@
/* ---- 校验组配是否全部完成 ---- */
function checkPackAllDone() {
var ingDone = allIngredients.every(function(ing) {
return ing.weighed >= ing.weightPerPack * ing.packSize;
return ing.weighed >= ing.weightPerPack;
});
var seaDone = allSeasonings.every(function(sea) {
return sea.weighed >= sea.weightPerPack * sea.packSize;
return sea.weighed >= sea.weightPerPack;
});
return ingDone && seaDone;
}
@@ -1071,8 +1060,8 @@
function handlePackDoneExit() {
if (!checkPackAllDone()) {
var msg = [];
var ingDone = allIngredients.every(function(ing) { return ing.weighed >= ing.weightPerPack * ing.packSize; });
var seaDone = allSeasonings.every(function(sea) { return sea.weighed >= sea.weightPerPack * sea.packSize; });
var ingDone = allIngredients.every(function(ing) { return ing.weighed >= ing.weightPerPack; });
var seaDone = allSeasonings.every(function(sea) { return sea.weighed >= sea.weightPerPack; });
if (!ingDone) msg.push('主辅材');
if (!seaDone) msg.push('调料');
showToast(msg.join('和') + '未完成称重', 2500, 'error');
@@ -1088,8 +1077,8 @@
function handlePackDoneContinue() {
if (!checkPackAllDone()) {
var msg = [];
var ingDone = allIngredients.every(function(ing) { return ing.weighed >= ing.weightPerPack * ing.packSize; });
var seaDone = allSeasonings.every(function(sea) { return sea.weighed >= sea.weightPerPack * sea.packSize; });
var ingDone = allIngredients.every(function(ing) { return ing.weighed >= ing.weightPerPack; });
var seaDone = allSeasonings.every(function(sea) { return sea.weighed >= sea.weightPerPack; });
if (!ingDone) msg.push('主辅材');
if (!seaDone) msg.push('调料');
showToast(msg.join('和') + '未完成称重', 2500, 'error');
@@ -1103,8 +1092,8 @@
var pk = task.mealPacks[i];
if (pk.packName === packName) continue;
/* 判断该包是否有待组配项 */
var ingPending = pk.ingredients.some(function(ing) { return ing.weighed < ing.weightPerPack * pk.packSize; });
var seaPending = pk.seasonings && pk.seasonings.some(function(sea) { return sea.weighed < sea.weightPerPack * pk.packSize; });
var ingPending = pk.ingredients.some(function(ing) { return ing.weighed < ing.weightPerPack; });
var seaPending = pk.seasonings && pk.seasonings.some(function(sea) { return sea.weighed < sea.weightPerPack; });
if (ingPending || seaPending) { nextPack = pk; break; }
}
}
@@ -203,14 +203,14 @@
/* 表格头(6列) */
.item-table__head {
display: grid; grid-template-columns: 1fr 0.55fr 0.35fr 0.55fr 0.55fr 50px; gap: 6px;
display: grid; grid-template-columns: 1fr 0.65fr 0.55fr 0.55fr 50px; gap: 6px;
padding: 6px 16px; background: rgba(0,0,0,0.2); font-size: 11px; color: rgba(255,255,255,0.4); font-weight: 500;
}
.item-table__body { display: flex; flex-direction: column; }
/* 餐品净菜包主行 */
.item-parent-row {
display: grid; grid-template-columns: 1fr 0.55fr 0.35fr 0.55fr 0.55fr 50px; gap: 6px;
display: grid; grid-template-columns: 1fr 0.65fr 0.55fr 0.55fr 50px; gap: 6px;
padding: 10px 16px; border-top: 1px solid rgba(255,255,255,0.04); align-items: center;
background: rgba(74,144,217,0.06); margin-bottom: 4px; border-radius: 6px;
}
@@ -342,10 +342,6 @@
<div class="stat-chip__icon stat-chip__icon--orange">&#x1F96C;</div>
<div><div class="stat-chip__value" id="statFoods">0</div><div class="stat-chip__label">净菜种类</div></div>
</div>
<div class="stat-chip">
<div class="stat-chip__icon stat-chip__icon--red">&#x1F4E6;</div>
<div><div class="stat-chip__value" id="statPacks">0</div><div class="stat-chip__label">总份数</div></div>
</div>
</div>
<!-- 任务列表 -->
@@ -573,7 +569,6 @@
var total = records.length;
var totalWeight = 0;
var foodSet = {};
var totalPacks = 0;
records.forEach(function(order) {
order.mealPacks.forEach(function(pack) {
pack.ingredients.forEach(function(ing) {
@@ -585,7 +580,6 @@
totalWeight += sea.weighed;
});
}
totalPacks += pack.packSize;
});
});
@@ -593,7 +587,6 @@
document.getElementById('statTotalLabel').textContent = totalLabel;
document.getElementById('statWeight').textContent = totalWeight;
document.getElementById('statFoods').textContent = Object.keys(foodSet).length;
document.getElementById('statPacks').textContent = totalPacks;
}
// 搜索输入处理
@@ -701,10 +694,10 @@
'<span class="task-card__status"><span class="status-badge ' + (orderAllDone ? 'status-badge--done' : 'status-badge--pending') + '">' + (orderAllDone ? '已完成' : '待组配') + '</span></span>';
taskCard.appendChild(header);
/* 表格头(6列:餐品净菜包名称 / 包装规格 / 打包份数 / 所需总重 / 已称 / 状态) */
/* 表格头(5列:餐品净菜包名称 / 包装规格 / 应称重量 / 已称重量 / 状态) */
var tableHead = document.createElement('div');
tableHead.className = 'item-table__head';
tableHead.innerHTML = '<div>餐品净菜包名称</div><div style="text-align:center">包装规格</div><div style="text-align:center">份数</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div>';
tableHead.innerHTML = '<div>餐品净菜包名称</div><div style="text-align:center">包装规格</div><div style="text-align:right">应称重量</div><div style="text-align:right">已称重量</div><div style="text-align:center">状态</div>';
taskCard.appendChild(tableHead);
/* 表格体 */
@@ -716,42 +709,31 @@
/* 主辅材合计 */
var ingNeed = 0, ingWeighed = 0;
pack.ingredients.forEach(function(ing) {
ingNeed += ing.weightPerPack * pack.packSize;
ingNeed += ing.weightPerPack;
ingWeighed += ing.weighed;
});
/* 调料合计 */
var seaNeed = 0, seaWeighed = 0;
if (pack.seasonings) {
pack.seasonings.forEach(function(sea) {
seaNeed += sea.weightPerPack * pack.packSize;
seaNeed += sea.weightPerPack;
seaWeighed += sea.weighed;
});
}
var totalNeed = Math.round((ingNeed + seaNeed) * 100) / 100;
var totalWeighed = Math.round((ingWeighed + seaWeighed) * 100) / 100;
var perPackWeight = Math.round((totalNeed / pack.packSize) * 100) / 100;
var perPackWeighed = Math.round((totalWeighed / pack.packSize) * 100) / 100;
var packDone = !hasPendingPack(pack);
/* 从包装规格中提取重量(如"大份800g"→800 */
var specMatch = pack.packSpec && pack.packSpec.match(/(\d+)g/);
var specWeight = specMatch ? parseInt(specMatch[1]) : perPackWeight;
var weightClass = packDone ? 'parent-weight--done' : '';
/* 按单份拆分,每份一行 */
for (var p = 0; p < pack.packSize; p++) {
var portionWeighed = packDone ? perPackWeighed : 0;
var weightClass = packDone ? 'parent-weight--done' : '';
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + ' <span style="font-size:10px;color:rgba(255,255,255,0.4)">第' + (p + 1) + '份/' + pack.packSize + '份</span></span></div>' +
'<div style="text-align:center"><span class="pack-spec-tag">' + (pack.packSpec || '—') + '</span></div>' +
'<div style="text-align:center"><span class="pack-size-tag">1</span></div>' +
'<div class="parent-weight ' + weightClass + '">' + specWeight + ' 克</div>' +
'<div class="parent-weight ' + weightClass + '">' + portionWeighed + ' 克</div>' +
'<div style="text-align:center"><span class="status-tag ' + (packDone ? 'status-tag--done' : 'status-tag--wait') + '">' + (packDone ? '已完成' : '待组配') + '</span></div>';
tableBody.appendChild(parentRow);
}
var parentRow = document.createElement('div');
parentRow.className = 'item-parent-row';
parentRow.innerHTML =
'<div class="parent-name"><div class="parent-icon">&#x1F4E6;</div><span class="parent-name__text">' + pack.packName + '</span></div>' +
'<div style="text-align:center"><span class="pack-spec-tag">' + (pack.packSpec || '—') + '</span></div>' +
'<div class="parent-weight ' + weightClass + '">' + totalNeed + ' 克</div>' +
'<div class="parent-weight ' + weightClass + '">' + totalWeighed + ' 克</div>' +
'<div style="text-align:center"><span class="status-tag ' + (packDone ? 'status-tag--done' : 'status-tag--wait') + '">' + (packDone ? '已完成' : '待组配') + '</span></div>';
tableBody.appendChild(parentRow);
});
taskCard.appendChild(tableBody);
@@ -60,56 +60,58 @@
flex: 1; display: flex; align-items: center; justify-content: center;
}
.seasoning-grid {
width: 640px;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(3, 120px);
gap: 8px;
grid-template-rows: repeat(3, 100px);
gap: 5px;
}
/* 信息格(第一列+第二列的第1、2行4格合并) */
/* 调料格基类 */
.seasoning-cell {
background: #1a2b4a; border: 1px solid rgba(255,255,255,0.08);
border-radius: 10px; padding: 8px 10px;
background: #1a2b4a; border: 1px solid rgba(255,255,255,0.06);
border-radius: 8px; padding: 4px 6px;
display: flex; flex-direction: column; justify-content: center;
transition: all 0.2s; position: relative; overflow: hidden;
font-size: 10px; color: rgba(255,255,255,0.5);
transition: all 0.2s; position: relative;
}
/* 信息格:位置0(油),2列×2行大格 */
.seasoning-cell--info {
grid-column: 1 / span 2; grid-row: 1 / span 2;
background: rgba(250,173,21,0.08); border-color: rgba(250,173,21,0.25);
align-items: center; justify-content: center; text-align: center; gap: 8px;
background: rgba(250,173,21,0.08); border: 2px solid rgba(250,173,21,0.3);
padding: 8px 10px; gap: 4px; cursor: pointer;
}
.seasoning-cell--info .info__icon { font-size: 36px; }
.seasoning-cell--info .info__title { font-size: 18px; font-weight: 700; color: #faad14; }
.seasoning-cell--info .info__weight { font-size: 13px; color: rgba(255,255,255,0.6); }
.seasoning-cell--info .info__label { font-size: 11px; color: rgba(255,255,255,0.4); }
.seasoning-cell--info .info__edit-hint { font-size: 10px; color: rgba(255,255,255,0.25); margin-top: 4px; }
/* 调料格 */
.seasoning-cell--info:hover { border-color: rgba(250,173,21,0.5); background: rgba(250,173,21,0.12); }
.seasoning-cell--info .sea-name {
font-size: 18px; font-weight: 700; color: #faad14; line-height: 1.2;
display: flex; align-items: center; gap: 4px; margin-bottom: 6px;
}
.seasoning-cell--info .sea-name-icon { font-size: 22px; }
.seasoning-cell--info .sea-fields {
display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px;
}
.seasoning-cell--info .sea-field {
display: flex; align-items: center; gap: 4px; font-size: 14px;
}
.seasoning-cell--info .sea-field__label { color: rgba(255,255,255,0.35); }
.seasoning-cell--info .sea-field__value { color: rgba(255,255,255,0.75); font-weight: 500; }
/* 调料格(位置1-11 */
.seasoning-cell--slot { cursor: pointer; }
.seasoning-cell--slot:hover {
border-color: rgba(74,144,217,0.4); background: rgba(74,144,217,0.06);
transform: translateY(-1px);
}
.seasoning-cell--occupied { border-color: rgba(255,255,255,0.15); }
.sea-slot__pos {
position: absolute; top: 4px; right: 6px;
font-size: 11px; color: rgba(255,255,255,0.25); font-weight: 600;
}
.seasoning-cell--slot:hover { border-color: rgba(74,144,217,0.3); background: rgba(74,144,217,0.06); }
.seasoning-cell--occupied { border-color: rgba(255,255,255,0.12); }
.sea-slot__name {
font-size: 14px; font-weight: 600; color: rgba(255,255,255,0.85);
text-align: center; margin-top: 4px;
line-height: 1.2; display: flex; align-items: center; gap: 4px;
margin-bottom: 4px;
}
.sea-slot__spec {
font-size: 11px; color: rgba(255,255,255,0.4); text-align: center; margin-top: 2px;
.sea-slot__name-icon { font-size: 16px; }
.sea-slot__fields {
display: grid; grid-template-columns: 1fr 1fr; gap: 2px 8px;
}
.sea-slot__weight-tag {
display: inline-block; font-size: 10px; padding: 1px 6px; border-radius: 3px;
background: rgba(250,173,21,0.12); color: #faad14; margin-top: 2px;
.sea-slot__field {
display: flex; gap: 3px; font-size: 11px; line-height: 1.4;
}
.sea-slot__empty {
font-size: 12px; color: rgba(255,255,255,0.2); text-align: center;
}
.sea-slot__icon { font-size: 22px; text-align: center; }
.sea-slot__field-label { color: rgba(255,255,255,0.35); }
.sea-slot__field-value { color: rgba(255,255,255,0.65); font-weight: 500; }
.sea-slot__empty { font-size: 11px; color: rgba(255,255,255,0.2); text-align: center; }
/* 下拉选择浮层 */
.select-overlay {
@@ -129,8 +131,9 @@
font-size: 11px; padding: 2px 8px; border-radius: 4px;
background: rgba(74,144,217,0.15); color: #4a90d9; font-weight: 600;
}
.select-panel__select-wrap { position: relative; flex: 1; }
.select-panel__select-row { display: flex; gap: 8px; align-items: center; }
/* 搜索框 */
.select-panel__search-wrap { position: relative; flex: 1; }
.select-panel__search-row { display: flex; gap: 8px; align-items: flex-start; }
.select-panel__btn--reset-inline {
padding: 10px 14px; border-radius: 8px; font-size: 13px; font-weight: 600;
cursor: pointer; transition: all 0.2s; border: none; font-family: inherit; flex-shrink: 0;
@@ -138,18 +141,32 @@
border: 1px solid rgba(255,255,255,0.1);
}
.select-panel__btn--reset-inline:hover { background: rgba(255,255,255,0.1); color: #fff; }
.select-panel__select {
.select-panel__search-input {
width: 100%; padding: 10px 14px; background: #121832;
border: 1px solid rgba(255,255,255,0.1); border-radius: 8px;
color: #fff; font-size: 14px; outline: none; transition: border-color 0.2s;
appearance: none; -webkit-appearance: none; cursor: pointer;
font-family: inherit;
}
.select-panel__select:focus { border-color: #4a90d9; }
.select-panel__select-arrow {
position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
font-size: 12px; color: rgba(255,255,255,0.4); pointer-events: none;
.select-panel__search-input:focus { border-color: #4a90d9; }
/* 搜索结果列表 */
.select-panel__search-results {
position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
background: #121832; border: 1px solid rgba(255,255,255,0.1);
border-radius: 0 0 8px 8px; max-height: 180px; overflow-y: auto;
display: none;
}
.select-panel__search-results.show { display: block; }
.select-panel__search-item {
padding: 10px 14px; cursor: pointer; font-size: 13px; color: rgba(255,255,255,0.8);
transition: background 0.15s; display: flex; align-items: center; gap: 8px;
}
.select-panel__search-item:hover { background: rgba(74,144,217,0.15); color: #fff; }
.select-panel__search-item--selected { background: rgba(74,144,217,0.2); color: #4a90d9; }
.select-panel__search-empty {
padding: 16px; text-align: center; font-size: 12px; color: rgba(255,255,255,0.3);
display: none;
}
.select-panel__search-empty.show { display: block; }
/* 重量输入行 */
.select-panel__weight-row { display: flex; align-items: center; gap: 10px; }
.select-panel__weight-label { font-size: 13px; color: rgba(255,255,255,0.6); flex-shrink: 0; }
@@ -207,7 +224,7 @@
<!-- 说明栏 -->
<div class="info-bar">
<span class="info-bar__icon">&#x1F4A1;</span>
<span class="info-bar__text">点击格子配置调料名称和放置重量。左上信息格固定为「油」,可修改放置重量。配置完成后点击「保存」生效。</span>
<span class="info-bar__text">点击格子配置调料名称和放置重量。配置完成后点击「保存」生效。</span>
<button class="info-bar__reset-btn" onclick="resetConfig()">重置</button>
<button class="info-bar__save-btn" onclick="saveConfig()">保存</button>
</div>
@@ -224,16 +241,12 @@
<!-- 下拉选择浮层 -->
<div class="select-overlay" id="selectOverlay">
<div class="select-panel">
<div class="select-panel__title">
选择调料
<span class="select-panel__pos-tag" id="posTag">位置 --</span>
</div>
<div class="select-panel__select-row">
<div class="select-panel__select-wrap">
<select class="select-panel__select" id="seasoningSelect">
<option value="">-- 请选择调料 --</option>
</select>
<span class="select-panel__select-arrow">&#x25BC;</span>
<div class="select-panel__title" id="selectTitle">选择调料</div>
<div class="select-panel__search-row">
<div class="select-panel__search-wrap">
<input type="text" class="select-panel__search-input" id="seasoningSearch" placeholder="搜索调料名称..." autocomplete="off">
<div class="select-panel__search-results" id="searchResults"></div>
<div class="select-panel__search-empty" id="searchEmpty">无匹配调料</div>
</div>
<button class="select-panel__btn--reset-inline" id="resetInlineBtn" onclick="resetSlot()">重置</button>
</div>
@@ -316,82 +329,61 @@
var config = loadConfig();
/* 渲染网格 */
/* 渲染网格(位置0=信息格 2×2,位置1-11=调料格) */
function renderGrid() {
var grid = document.getElementById('seasoningGrid');
grid.innerHTML = '';
/* 信息格:固定显示"油" */
/* 位置0:信息格(油),2列×2行大格 */
var infoCell = document.createElement('div');
infoCell.className = 'seasoning-cell seasoning-cell--info';
var oilCfg = config[0] || { name: '油', weight: 0 };
infoCell.innerHTML =
'<div class="info__icon">&#x1F6E2;</div>' +
'<div class="info__title">油</div>' +
'<div class="info__weight"><span class="info__label">放置重量:</span> ' + oilCfg.weight + 'g</div>' +
'<div class="info__edit-hint">点击修改重量</div>';
infoCell.style.cursor = 'pointer';
infoCell.onclick = function() { openSelect(0); };
var oilCfg = config[0];
if (oilCfg && oilCfg.name) {
var opt = SEASONING_OPTIONS.find(function(o) { return o.name === oilCfg.name; });
var icon = opt ? opt.icon : '&#x1F6E2;';
infoCell.innerHTML =
'<div class="sea-name"><span class="sea-name-icon">' + icon + '</span>' + oilCfg.name + '</div>' +
'<div class="sea-fields">' +
'<div class="sea-field"><span class="sea-field__value">' + (oilCfg.weight || 0) + 'g</span></div>' +
'</div>';
} else {
infoCell.innerHTML = '<div class="sea-name" style="color:rgba(255,255,255,0.3)">点击配置</div>';
}
infoCell.onclick = (function(p) { return function() { openSelect(p); }; })(0);
grid.appendChild(infoCell);
/* 11 个调料位置 */
/* 位置1-11:普通调料格 */
for (var pos = 1; pos <= 11; pos++) {
var cell = document.createElement('div');
cell.className = 'seasoning-cell seasoning-cell--slot';
var cfg = config[pos];
if (cfg && cfg.name) {
cell.classList.add('seasoning-cell--occupied');
var opt = SEASONING_OPTIONS.find(function(o) { return o.name === cfg.name; });
var icon = opt ? opt.icon : '&#x1F9C2;';
var opt2 = SEASONING_OPTIONS.find(function(o) { return o.name === cfg.name; });
var icon2 = opt2 ? opt2.icon : '&#x1F9C2;';
cell.innerHTML =
'<span class="sea-slot__pos">' + pos + '</span>' +
'<div class="sea-slot__icon">' + icon + '</div>' +
'<div class="sea-slot__name">' + cfg.name + '</div>' +
'<div class="sea-slot__weight-tag">' + (cfg.weight || 0) + 'g</div>';
'<div class="sea-slot__name"><span class="sea-slot__name-icon">' + icon2 + '</span>' + cfg.name + '</div>' +
'<div class="sea-slot__fields">' +
'<div class="sea-slot__field"><span class="sea-slot__field-value">' + (cfg.weight || 0) + 'g</span></div>' +
'</div>';
} else {
cell.innerHTML =
'<span class="sea-slot__pos">' + pos + '</span>' +
'<div class="sea-slot__empty">点击配置</div>';
cell.innerHTML = '<div class="sea-slot__empty">点击配置</div>';
}
cell.onclick = (function(p) { return function() { openSelect(p); }; })(pos);
grid.appendChild(cell);
}
}
/* 打开下拉选择 */
/* 打开选择弹窗(所有位置统一体验) */
function openSelect(pos) {
editingPos = pos;
document.getElementById('posTag').textContent = pos === 0 ? '信息格 (油)' : '位置 ' + pos;
/* 信息格时调整标题 */
var resetBtn = document.getElementById('resetInlineBtn');
if (pos === 0) {
document.querySelector('.select-panel__title').firstChild.textContent = '修改油量 ';
resetBtn.textContent = '恢复默认';
} else {
document.querySelector('.select-panel__title').firstChild.textContent = '选择调料 ';
resetBtn.textContent = '重置';
}
document.getElementById('selectTitle').textContent = '选择调料';
/* 填充下拉选项 */
var select = document.getElementById('seasoningSelect');
select.innerHTML = '<option value="">-- 请选择调料 --</option>';
SEASONING_OPTIONS.forEach(function(o) {
var opt = document.createElement('option');
opt.value = o.name;
opt.textContent = o.name;
if (config[pos] && config[pos].name === o.name) opt.selected = true;
select.appendChild(opt);
});
/* 信息格固定为油,禁用下拉 */
if (pos === 0) {
select.value = '油';
select.disabled = true;
select.style.opacity = '0.6';
} else {
select.disabled = false;
select.style.opacity = '1';
}
var searchInput = document.getElementById('seasoningSearch');
searchInput.value = config[pos] && config[pos].name ? config[pos].name : '';
searchInput.disabled = false;
searchInput.style.opacity = '1';
renderSearchResults('');
/* 填充重量 */
var weightInput = document.getElementById('seasoningWeight');
@@ -402,21 +394,17 @@
/* 确认选择 */
function confirmSelect() {
var select = document.getElementById('seasoningSelect');
var name = select.value;
var name = document.getElementById('seasoningSearch').value.trim();
var weight = parseFloat(document.getElementById('seasoningWeight').value) || 0;
if (editingPos === 0) {
/* 信息格只改重量 */
config[0] = { name: '油', weight: weight };
renderGrid();
closeSelect();
showToast('油的放置重量已更新为 ' + weight + 'g', 1500, 'success');
if (!name) {
showToast('请输入或选择调料名称', 1500, 'error');
return;
}
if (!name) {
showToast('请选择调料', 1500, 'error');
/* 检查是否在候选清单中 */
var found = SEASONING_OPTIONS.find(function(o) { return o.name === name; });
if (!found) {
showToast('调料"' + name + '"不在候选清单中', 1500, 'error');
return;
}
config[editingPos] = { name: name, weight: weight };
@@ -427,14 +415,6 @@
/* 清空位置(重量归零,保留调料名称) */
function clearSlot() {
if (editingPos === 0) {
/* 信息格重量归零 */
config[0] = { name: '油', weight: 0 };
document.getElementById('seasoningWeight').value = '0';
renderGrid();
showToast('油重量已清零', 1500, 'success');
return;
}
if (config[editingPos] && config[editingPos].name) {
config[editingPos].weight = 0;
} else {
@@ -445,21 +425,14 @@
showToast('位置 ' + editingPos + ' 重量已清零', 1500, 'success');
}
/* 重置调料选择(清除下拉选中,清空重量输入) */
/* 重置调料选择(清除搜索框,清空重量输入) */
function resetSlot() {
var select = document.getElementById('seasoningSelect');
var searchInput = document.getElementById('seasoningSearch');
var weightInput = document.getElementById('seasoningWeight');
if (editingPos === 0) {
/* 信息格:重量恢复默认值 */
select.value = '油';
weightInput.value = '1000';
config[0] = { name: '油', weight: 1000 };
renderGrid();
showToast('油重量已恢复默认 1000g', 1500, 'success');
return;
}
select.value = '';
searchInput.value = '';
weightInput.value = '';
document.getElementById('searchResults').classList.remove('show');
document.getElementById('searchEmpty').classList.remove('show');
showToast('位置 ' + editingPos + ' 调料选择已清除', 1500, 'success');
}
@@ -467,6 +440,47 @@
function closeSelect() {
editingPos = -1;
document.getElementById('selectOverlay').classList.remove('show');
document.getElementById('searchResults').classList.remove('show');
document.getElementById('searchEmpty').classList.remove('show');
}
/* 渲染搜索结果列表 */
function renderSearchResults(query) {
var resultsEl = document.getElementById('searchResults');
var emptyEl = document.getElementById('searchEmpty');
resultsEl.innerHTML = '';
resultsEl.classList.remove('show');
emptyEl.classList.remove('show');
var filtered = SEASONING_OPTIONS;
if (query) {
var q = query.toLowerCase();
filtered = SEASONING_OPTIONS.filter(function(o) {
return o.name.toLowerCase().indexOf(q) >= 0;
});
}
if (filtered.length === 0) {
emptyEl.classList.add('show');
return;
}
filtered.forEach(function(o) {
var item = document.createElement('div');
item.className = 'select-panel__search-item';
var currentName = document.getElementById('seasoningSearch').value;
if (o.name === currentName) {
item.classList.add('select-panel__search-item--selected');
}
item.innerHTML = o.icon + ' ' + o.name;
item.onclick = function() {
document.getElementById('seasoningSearch').value = o.name;
resultsEl.classList.remove('show');
emptyEl.classList.remove('show');
};
resultsEl.appendChild(item);
});
resultsEl.classList.add('show');
}
/* 保存配置 */
@@ -510,6 +524,23 @@
}
})();
/* 搜索框输入事件 */
document.getElementById('seasoningSearch').addEventListener('input', function() {
renderSearchResults(this.value);
});
/* 点击搜索框时显示全部候选 */
document.getElementById('seasoningSearch').addEventListener('focus', function() {
renderSearchResults(this.value);
});
/* 点击空白处关闭搜索结果 */
document.addEventListener('click', function(e) {
var wrap = document.querySelector('.select-panel__search-wrap');
if (wrap && !wrap.contains(e.target)) {
document.getElementById('searchResults').classList.remove('show');
document.getElementById('searchEmpty').classList.remove('show');
}
});
/* 初始化 */
renderGrid();
</script>
@@ -1,5 +1,13 @@
# 净菜组配秤 CHANGELOG
## [2.2.3] - 2026-07-06
### 移除份数列 + 调料设置页重构
- `01-packing-tasks.html` — 移除"份数"列,grid 7列→6列;移除按 packSize 拆分行逻辑
- `02-weighing-packing.html` — 移除"组配份数"字段和行拆分;移除主辅材和调料的"每份"/"每份用量"字段
- `03-verify-history.html` — 移除"总份数"统计标签和行拆分,grid 6列→5列
- `04-seasoning-settings.html` — 弹窗从下拉框改为搜索框(含搜索结果列表/空状态);油格改为2×2金色信息格,与组配页视觉风格对齐;所有调料弹窗统一体验;移除位置编号;去掉"放置重量"标签
## [2.2.2] - 2026-06-26
### 组配任务页按单份拆分 + 组配作业页移除弹窗