diff --git a/web-admin/nutrition/doc/CHANGELOG.md b/web-admin/nutrition/doc/CHANGELOG.md index 22a483e..4596de0 100644 --- a/web-admin/nutrition/doc/CHANGELOG.md +++ b/web-admin/nutrition/doc/CHANGELOG.md @@ -1,5 +1,11 @@ # 营养用餐管理端 CHANGELOG +## [2026-09-01] feat: 净菜订单生成历史加建议熟重/规格列 + 食谱快速创建份数改规格 + +- `prod-clean-order.html` 净菜订单: + - 「净菜订单生成历史」弹窗新增「建议熟重(kg)」列(按就餐人数推算所需熟重)与「规格」列(规格重量/规格名称,读取自有餐品库-餐品定价规格) + - 「由食谱快速创建订单」弹窗餐品明细「份数」改为「规格」下拉(规格重量/规格名称),份数按所选规格自动计算(每份生重>4kg 按 4kg/份反算,否则=就餐人数) + ## [2026-08-31] feat: 餐线营养秤概览筛选栏下沉 + 重量变化折线图 - `din-terminal.html` 设备概览「餐线营养秤」: diff --git a/web-admin/nutrition/prod-clean-order.html b/web-admin/nutrition/prod-clean-order.html index 7b8b660..6e31043 100644 --- a/web-admin/nutrition/prod-clean-order.html +++ b/web-admin/nutrition/prod-clean-order.html @@ -369,7 +369,7 @@ tr.detail-row td.td-actions{background:#FAFBFC;box-shadow:-4px 0 8px rgba(0,0,0,
餐品明细(重复餐品已自动合并,请逐道确认是否需要内配调料)
- +
菜品名称份数内配调料
菜品名称规格内配调料
@@ -414,7 +414,7 @@ tr.detail-row td.td-actions{background:#FAFBFC;box-shadow:-4px 0 8px rgba(0,0,0,
- +
食谱日期餐次餐品名称就餐人数内配料(是否)打包份数预定配送时间开始生成时间生成成功时间
食谱日期餐次餐品名称就餐人数建议熟重(kg)内配料(是否)规格打包份数预定配送时间开始生成时间生成成功时间
@@ -855,12 +855,16 @@ function renderGenHistoryOrder(orderNo){ var infoBody=document.getElementById('genHistoryInfoBody'); var html=''; rec.details.forEach(function(d){ + var spec=getDishSpecForRecipe(d.foodName); + var specLabel=spec.baseGram+'g/'+spec.portion; html+='' +''+rec.recipeDate+'' +''+d.meal+'' +''+d.foodName+'' +''+d.dinerCount+'' + +''+(parseFloat(d.cookedWeight).toFixed(2))+' kg' +''+genSeasoningTag(d.needSeasoning)+'' + +''+specLabel+'' +''+d.servings+'' +''+rec.deliverTime+'' +''+rec.startTime+'' @@ -1441,6 +1445,12 @@ function getDishSpecForRecipe(name){ } return RECIPE_FALLBACK[name]||{portion:'标准份',baseGram:500,unit:'份'}; } +/* 食谱餐品可选规格列表:优先总库多规格,无则回退单规格 */ +function getDishSpecOptionsForRecipe(name){ + var specs=getSpecsByDish(name); + if(specs&&specs.length>0)return specs; + return [getDishSpecForRecipe(name)]; +} var MEAL_NAMES=['早餐','午餐','晚餐','加餐']; function getDefaultDate(){return '2026-05-20';} @@ -1499,8 +1509,8 @@ function onRecipeDateChange(){ /* ========== 餐品调料配置表(食谱快速创建专用) ========== */ /* recipeSeasoningMap: { 菜名: true|false },跨餐次重复菜品自动合并,状态在重渲时保留 */ var recipeSeasoningMap={}; -/* recipeServingMap: { 菜名: 份数 },餐品明细表份数编辑值,重渲时保留 */ -var recipeServingMap={}; +/* recipeSpecMap: { 菜名: "baseGram|portion|unit" },餐品明细表所选规格,重渲时保留 */ +var recipeSpecMap={}; function renderDishSeasoningTable(){ var section=document.getElementById('dishSeasoningSection'); var tbody=document.getElementById('dishSeasoningBody'); @@ -1533,23 +1543,21 @@ function renderDishSeasoningTable(){ /* 未配置过的菜品默认 false(不需要);已配置的保留 */ if(typeof recipeSeasoningMap[name]!=='boolean')recipeSeasoningMap[name]=false; var ns=recipeSeasoningMap[name]===true; - /* 每份生重(克)取系统默认规格;就餐人数为该菜品跨餐次累加值 */ - var sp=getDishSpecForRecipe(name); - var baseGram=sp.baseGram||500; - var dinerCount=dishDinerMap[name]||0; - /* 预测生重(总,克)= 每份生重 × 就餐人数 */ - var predictedRawG=baseGram*dinerCount; - /* 份数:每份生重>4kg 时按最大包装克重 4kg/份 反算,否则取就餐人数 */ - if(!recipeServingMap[name]){ - recipeServingMap[name]=baseGram>4000?Math.ceil(predictedRawG/4000):dinerCount; + /* 规格列表:优先总库多规格,无则回退单规格 */ + var specs=getDishSpecOptionsForRecipe(name); + /* 首次渲染默认选中第一个规格 */ + if(!recipeSpecMap[name]&&specs.length>0){ + recipeSpecMap[name]=specs[0].baseGram+'|'+specs[0].portion+'|'+(specs[0].unit||'份'); } - var servings=recipeServingMap[name]; + var selVal=recipeSpecMap[name]; html+=''+name+''; - /* 份数:固定单位「份」,输入框编辑份数 */ - html+='
' - +'' - +'' - +'
'; + /* 规格:下拉选择 规格重量/规格名称 */ + html+=''; html+='
'; html+=''; html+=''; @@ -1560,9 +1568,9 @@ function renderDishSeasoningTable(){ function updateRecipeSeasoning(name,val){ recipeSeasoningMap[name]=!!val; } -/* 更新食谱餐品份数 */ -function updateRecipeServing(name,val){ - recipeServingMap[name]=parseInt(val,10)||0; +/* 更新食谱餐品所选规格 */ +function updateRecipeSpec(name,val){ + recipeSpecMap[name]=val; } /* 校验所选餐次是否都已填写就餐人数,并返回缺失餐次名 */ @@ -1628,15 +1636,25 @@ function submitRecipeOrder(){ for(var name in dishMap){ var item=dishMap[name]; var sp=item.spec; - /* 包装规格固定为「份」,份数优先取餐品明细表编辑值,未编辑回退就餐人数 */ var baseGram=sp.baseGram||500; - var unit='份'; - var servings=recipeServingMap[name]||item.dinerCount; + var portion=sp.portion||'标准份'; + var unit=sp.unit||'份'; + /* 采用餐品明细表所选规格 */ + if(recipeSpecMap[name]){ + var spParts=recipeSpecMap[name].split('|'); + if(spParts.length>=2){ + baseGram=parseFloat(spParts[0])||baseGram; + portion=spParts[1]||portion; + unit=spParts[2]||'份'; + } + } + /* 份数按所选规格自动计算:每份生重>4kg 时按 4kg/份 反算,否则=就餐人数 */ + var servings=baseGram>4000?Math.ceil(baseGram*item.dinerCount/4000):item.dinerCount; newLines.push({ id:'L'+(Date.now()+di), ncType:'cp',foodName:name, spec:baseGram+'g/'+unit, - portion:sp.portion,baseGram:baseGram,unit:unit, + portion:portion,baseGram:baseGram,unit:unit, qty:servings, dinerCount:item.dinerCount, weight:parseFloat((baseGram*item.dinerCount/1000).toFixed(2)), @@ -1670,7 +1688,7 @@ function sanitizeIntegerInput(el){el.value=el.value.replace(/[^\d]/g,'');} document.getElementById('recipeDeliveryTime').value=getDefaultDeliveryTime(); document.getElementById('dailyMenuSection').style.display='none'; recipeSeasoningMap={}; - recipeServingMap={}; + recipeSpecMap={}; onRecipeDateChange(); } if(id==='modal-gen-history'){document.getElementById('ghDate').value='';renderGenHistory();}