From 0b4e15c3a443cc56b771486a15be20264d06c2c4 Mon Sep 17 00:00:00 2001 From: fengpu <18691763612@163.com> Date: Wed, 23 Sep 2026 09:30:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=87=80=E8=8F=9C=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E6=98=8E=E7=BB=86=E6=96=B0=E5=A2=9E=E6=91=86=E6=94=BE=E9=A1=BA?= =?UTF-8?q?=E5=BA=8F=E4=B8=8E=E7=90=86=E7=94=B1=EF=BC=8C=E7=B2=BE=E7=AE=80?= =?UTF-8?q?=E5=8F=96=E9=A4=90/=E4=BD=99=E9=87=8F=E5=A4=84=E7=BD=AE/?= =?UTF-8?q?=E6=98=8E=E7=BB=86=E5=88=97=E8=A1=A8=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- web-admin/nutrition/din-order-pickup.html | 9 +-- web-admin/nutrition/doc/CHANGELOG.md | 8 ++ .../nutrition/prod-clean-order-history.html | 81 +++++++++++-------- web-admin/nutrition/prod-proc-surplus.html | 18 ++--- 4 files changed, 69 insertions(+), 47 deletions(-) diff --git a/web-admin/nutrition/din-order-pickup.html b/web-admin/nutrition/din-order-pickup.html index 09d6f49..94df2cf 100644 --- a/web-admin/nutrition/din-order-pickup.html +++ b/web-admin/nutrition/din-order-pickup.html @@ -859,15 +859,14 @@ function buildRawDataModal(data) { const statusTag = recStatus === '已识别' ? '已识别' : '未识别'; const samples = [ - { t: minusSeconds(data.time, 5), w: (data.weight - 38).toFixed(1), d: '+' + (data.weight - 38).toFixed(1), stable: '否' }, - { t: minusSeconds(data.time, 2), w: (data.weight - 9).toFixed(1), d: '+29.0', stable: '否' }, - { t: data.time, w: data.weight.toFixed(1), d: '+9.0', stable: '是' } + { t: minusSeconds(data.time, 5), w: (data.weight - 38).toFixed(1), stable: '否' }, + { t: minusSeconds(data.time, 2), w: (data.weight - 9).toFixed(1), stable: '否' }, + { t: data.time, w: data.weight.toFixed(1), stable: '是' } ]; const rowsHtml = samples.map(s => ` ${s.t} ${s.w} - ${s.d} ${statusTag} ${recUser} ${s.stable === '是' ? '' : ''} @@ -878,7 +877,7 @@ function buildRawDataModal(data) {
设备名称:${data.device}
- + ${rowsHtml}
采样时间当前重量(g)较上次变化重量(g)识别状态用户是否稳定
采样时间当前重量(g)识别状态用户是否稳定
`; diff --git a/web-admin/nutrition/doc/CHANGELOG.md b/web-admin/nutrition/doc/CHANGELOG.md index 26342e0..c19d189 100644 --- a/web-admin/nutrition/doc/CHANGELOG.md +++ b/web-admin/nutrition/doc/CHANGELOG.md @@ -1,5 +1,13 @@ # 营养用餐管理端 CHANGELOG +## [2026-09-23] feat: 净菜订单明细新增摆放顺序与理由,三页列表字段精简 + +- `prod-clean-order-history.html` 净菜订单生成历史「数据明细」弹窗: + - 餐品维度新增「摆放顺序」「摆放理由」两列:按餐线取餐动线(先取菜后取主食)对荤菜/素菜/主食/汤/饮品分类赋序,餐次分组内排序编号并给出摆放理由 + - 删除各环节数值下方的差异率趋势徽标(↑ 超 X% / ↓ 省 X% / — 持平),单元格仅保留数值;餐品展开的食材子表同步删除「差异率」列 +- `din-order-pickup.html` 取餐管理「秤原始数据」弹窗:删除「较上次变化重量(g)」列 +- `prod-proc-surplus.html` 余量处置列表:删除「交叉核对状态」字段(表头与各行「正常/异常(损耗超标)」标签),详情抽屉按表头动态渲染自动同步移除 + ## [2026-09-21] feat: 净菜订单生成历史双维度全链路对账 + 食物成分价格变更历史弹窗 - `prod-clean-order-history.html` 净菜订单生成历史「数据明细」弹窗重构为餐品/食材双维度对账视图: diff --git a/web-admin/nutrition/prod-clean-order-history.html b/web-admin/nutrition/prod-clean-order-history.html index b1851da..7db5fb0 100644 --- a/web-admin/nutrition/prod-clean-order-history.html +++ b/web-admin/nutrition/prod-clean-order-history.html @@ -124,8 +124,6 @@ tbody tr:hover{background:#F8FBFF;} .val{font-weight:600;} .val--base{color:var(--primary);} .val-empty{color:var(--text-placeholder);font-weight:400;} -.val-diff{margin-top:3px;line-height:1;} -.tag--mini{font-size:10px;padding:1px 6px;border-radius:8px;} /* 空态 */ .empty-state{text-align:center;color:var(--text-placeholder);padding:60px 0;font-size:var(--font-sm);} .empty-state .icon{font-size:40px;display:block;margin-bottom:12px;} @@ -221,6 +219,8 @@ tbody tr:hover{background:#F8FBFF;} 餐次 餐品名称 + 摆放顺序 + 摆放理由 熟重环节 取餐环节 @@ -297,6 +297,23 @@ var ING_TYPE_CLS={'主材':'ing-type--main','辅材':'ing-type--aux','调料':'i var ING_YIELD={'鸡胸肉':0.88,'花生米':0.98,'黄瓜':0.85,'干辣椒':1,'葱姜蒜':0.9,'鲈鱼':0.82,'姜片':0.9,'葱丝':0.9,'五花肉':0.88,'酱油':1,'冰糖':1,'八角':1,'嫩豆腐':0.95,'肉末':0.9,'豆瓣酱':1,'花椒':1,'番茄':0.92,'鸡蛋':0.98,'葱花':0.9,'西兰花':0.82,'胡萝卜':0.88,'大蒜':0.88,'小米':1,'清水':1,'大米':1,'黄豆':1,'面粉':1,'酵母':1,'猪里脊':0.9,'木耳':1,'青椒':0.88,'猪排骨':0.85,'白糖':1,'香醋':1,'紫菜':1,'冬瓜':0.85,'酸奶':1,'茶叶':1}; /* AI 预测熟成率(生重→熟重) */ var COOK_YIELD=0.85; +/* 餐线摆放规则:分类 → 摆放顺序权重 + 摆放理由(取餐动线:先取菜后取主食) */ +var DISH_PLACE_CAT={ + '荤菜':{order:1,reason:'主菜优先摆放,突出餐品重心'}, + '素菜':{order:2,reason:'素菜紧随主菜,均衡营养搭配'}, + '主食':{order:3,reason:'主食随后摆放,便于按需取量'}, + '汤':{order:4,reason:'汤品靠后摆放,避免取餐洒漏'}, + '饮品':{order:5,reason:'饮品置于末端,便于即取即走'} +}; +/* 菜品 → 摆放分类 */ +var DISH_CAT={ + '宫保鸡丁':'荤菜','清蒸鲈鱼':'荤菜','红烧肉':'荤菜','番茄炒蛋':'荤菜','糖醋排骨':'荤菜', + '鱼香肉丝':'荤菜','麻婆豆腐':'荤菜','糖醋里脊':'荤菜','煮鸡蛋':'荤菜','茶叶蛋':'荤菜', + '炒时蔬':'素菜','清炒西兰花':'素菜', + '米饭':'主食','馒头':'主食','白粥':'主食','小米粥':'主食', + '冬瓜排骨汤':'汤','紫菜蛋花汤':'汤', + '豆浆':'饮品','酸奶':'饮品' +}; function round2(n){return parseFloat(n.toFixed(2));} /* ========== 净菜订单生成历史数据(订单维度,一个订单可含多个餐次) ========== */ @@ -403,7 +420,7 @@ function nameHash(s){ /* 餐品维度:AI 预测双值(生重/熟重)+ 下单/组配/烹制/取餐各环节实际值 */ function deriveDetail(order){ var generating=order.genStatus==='generating'; - return order.details.map(function(d){ + var list=order.details.map(function(d){ var bom=recipeBom[d.foodName]||[]; var baseRatio=d.actualRatio!=null?d.actualRatio:(order.actualRatio||1); var perDishGram=bom.reduce(function(s,i){return s+i.perServing;},0); @@ -426,13 +443,23 @@ function deriveDetail(order){ var ingAct=parseFloat((ingRec*ingRatio).toFixed(3)); return {name:ing.name,type:ing.type,perServing:ing.perServing,rec:ingRec,act:ingAct}; }); + var cat=DISH_CAT[d.foodName]||'主食'; + var place=DISH_PLACE_CAT[cat]||DISH_PLACE_CAT['主食']; return { meal:d.meal,foodName:d.foodName,spec:d.spec,dinerCount:d.dinerCount,servings:d.servings,needSeasoning:d.needSeasoning, recRaw:recRaw,recCooked:recCooked, orderWeight:orderWeight,comboRaw:comboRaw,cookCooked:cookCooked,actualDiner:actualDiner,pickupWeight:pickupWeight, - ingredients:ingredients + ingredients:ingredients, + placeWeight:place.order,placeReason:place.reason }; }); + /* 按餐次分组,组内按餐线动线排序赋摆放序号 */ + var byMeal={}; + list.forEach(function(d){if(!byMeal[d.meal])byMeal[d.meal]=[];byMeal[d.meal].push(d);}); + Object.keys(byMeal).forEach(function(meal){ + byMeal[meal].slice().sort(function(a,b){return a.placeWeight-b.placeWeight;}).forEach(function(d,i){d.placeOrder=i+1;}); + }); + return list; } /* 食材维度:同一食材跨餐品合并一行,链路覆盖 AI 用量→采购/实收(毛)→净菜产出(净)→组配实际(净) */ @@ -464,15 +491,6 @@ function deriveIngredients(order){ }); } -/* ========== 差异率 ========== */ -function diffInfo(act,rec){ - if(!rec)return {cls:'flat',text:'— 持平'}; - var pct=(act-rec)/rec*100; - if(pct>1)return {cls:'tag-red',text:'↑ 超 '+pct.toFixed(1)+'%'}; - if(pct<-1)return {cls:'tag-green',text:'↓ 省 '+Math.abs(pct).toFixed(1)+'%'}; - return {cls:'tag-gray',text:'— 持平'}; -} - /* ========== 菜品种类(去重) ========== */ function distinctDishCount(o){ var set={}; @@ -616,21 +634,18 @@ function switchDim(dim){ document.getElementById('dimIngWrap').style.display=dim==='ing'?'':'none'; } -/* ========== 数值 + 差异徽标单元格(生成中环节未发生时占位 —) ========== */ -function stageCell(val,rec){ +/* ========== 数值单元格(生成中环节未发生时占位 —) ========== */ +function stageCell(val){ if(val==null)return ''; - var diff=diffInfo(val,rec); - return '
'+val.toFixed(2)+'
'+diff.text+'
'; + return '
'+val.toFixed(2)+'
'; } -function dinerCell(actual,plan){ +function dinerCell(actual){ if(actual==null)return ''; - var diff=diffInfo(actual,plan); - return '
'+actual+'
'+diff.text+'
'; + return '
'+actual+'
'; } -function ingStageCell(val,rec){ - if(val==null||rec==null)return ''; - var diff=diffInfo(val,rec); - return '
'+val.toFixed(3)+'
'+diff.text+'
'; +function ingStageCell(val){ + if(val==null)return ''; + return '
'+val.toFixed(3)+'
'; } function plainCell(val){ if(val==null)return ''; @@ -645,16 +660,18 @@ function renderDishRows(details){ html+=''; html+=''+d.meal+''; html+=''+d.foodName+''; + html+=''+d.placeOrder+''; + html+=''+d.placeReason+''; /* 熟重环节 */ html+=''+d.recCooked.toFixed(2)+''; - html+=stageCell(d.cookCooked,d.recCooked); + html+=stageCell(d.cookCooked); /* 取餐环节 */ html+=''+d.dinerCount+''; - html+=dinerCell(d.actualDiner,d.dinerCount); - html+=stageCell(d.pickupWeight,d.recCooked); + html+=dinerCell(d.actualDiner); + html+=stageCell(d.pickupWeight); html+=''; html+=''; - html+=''+buildIngredientsDetail(d)+''; + html+=''+buildIngredientsDetail(d)+''; html+=''; }); document.getElementById('detailDishBody').innerHTML=html; @@ -672,12 +689,12 @@ function renderIngRows(ings){ html+=''+m.aiUsed.toFixed(3)+''; /* 采供环节:采购(链路起点)+ 实收 vs 采购(收货损耗) */ html+=plainCell(m.purchase); - html+=ingStageCell(m.received,m.purchase); + html+=ingStageCell(m.received); /* 加工环节:出净率 + 净菜产出 */ html+=''+(m.received!=null?(m.yieldRate*100).toFixed(0)+'%':'—')+''; html+=plainCell(m.netOut); /* 组配环节:实际用量 vs AI 生成用量(核心对账) */ - html+=ingStageCell(m.comboUsed,m.aiUsed); + html+=ingStageCell(m.comboUsed); html+=''; html+=''; html+=''+buildUsedByDetail(m)+''; @@ -688,16 +705,14 @@ function renderIngRows(ings){ document.querySelector('.modal-mask').addEventListener('click',function(e){if(e.target===this)closeDetail();}); function buildIngredientsDetail(d){ - var html=''; + var html='
食材名称类别推荐总量(kg)组配实际用量(kg)差异率
'; d.ingredients.forEach(function(ing){ var cls=ING_TYPE_CLS[ing.type]||''; - var diff=diffInfo(ing.act,ing.rec); html+=''; html+=''; html+=''; html+=''; html+=''; - html+=''; html+=''; }); html+='
食材名称类别推荐总量(kg)组配实际用量(kg)
'+ing.name+''+ing.type+''+ing.rec.toFixed(3)+''+ing.act.toFixed(3)+''+diff.text+'
'; diff --git a/web-admin/nutrition/prod-proc-surplus.html b/web-admin/nutrition/prod-proc-surplus.html index 731ffd1..59dc86c 100644 --- a/web-admin/nutrition/prod-proc-surplus.html +++ b/web-admin/nutrition/prod-proc-surplus.html @@ -190,16 +190,16 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
余量处置
- + - - - - - - - - + + + + + + + +
处置单号菜品名称餐线餐次实际制作(kg)销售/取餐(kg)余量(kg)余量率(%)处置方式备注处置数量(kg)交叉核对状态处置时间处置人员操作
处置单号菜品名称餐线餐次实际制作(kg)销售/取餐(kg)余量(kg)余量率(%)处置方式备注处置数量(kg)处置时间处置人员操作
SUR-002白米饭A区中餐线午餐62.054.08.012.9%捐赠捐赠予未央环卫5.0正常2026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-002白米饭A区中餐线午餐62.054.08.012.9%员工福利加班餐3.0正常2026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-004蒜蓉菠菜B区中餐线午餐14.810.04.832.4%废弃叶片发黄3.0异常(损耗超标)2026-04-22 15:00李主管食材溯源链路 查看视频 更多 ▾
SUR-004蒜蓉菠菜B区中餐线午餐14.810.04.832.4%加工再利用制作蔬菜饼1.8异常(损耗超标)2026-04-22 15:00李主管食材溯源链路 查看视频 更多 ▾
SUR-001宫保鸡丁A区中餐线午餐43.039.53.58.1%员工福利加班餐2.0正常2026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-001宫保鸡丁A区中餐线午餐43.039.53.58.1%捐赠捐赠予安保部1.5正常2026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-005红烧肉B区中餐线午餐48.545.33.26.6%员工福利加班餐3.2正常2026-04-22 14:45张主管食材溯源链路 查看视频 更多 ▾
SUR-003香辣大虾C区快餐线午餐20.518.32.210.7%废弃只剩辣椒和虾头2.2正常2026-04-22 14:30张主管食材溯源链路 查看视频 更多 ▾
SUR-002白米饭A区中餐线午餐62.054.08.012.9%捐赠捐赠予未央环卫5.02026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-002白米饭A区中餐线午餐62.054.08.012.9%员工福利加班餐3.02026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-004蒜蓉菠菜B区中餐线午餐14.810.04.832.4%废弃叶片发黄3.02026-04-22 15:00李主管食材溯源链路 查看视频 更多 ▾
SUR-004蒜蓉菠菜B区中餐线午餐14.810.04.832.4%加工再利用制作蔬菜饼1.82026-04-22 15:00李主管食材溯源链路 查看视频 更多 ▾
SUR-001宫保鸡丁A区中餐线午餐43.039.53.58.1%员工福利加班餐2.02026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-001宫保鸡丁A区中餐线午餐43.039.53.58.1%捐赠捐赠予安保部1.52026-04-22 14:00张主管食材溯源链路 查看视频 更多 ▾
SUR-005红烧肉B区中餐线午餐48.545.33.26.6%员工福利加班餐3.22026-04-22 14:45张主管食材溯源链路 查看视频 更多 ▾
SUR-003香辣大虾C区快餐线午餐20.518.32.210.7%废弃只剩辣椒和虾头2.22026-04-22 14:30张主管食材溯源链路 查看视频 更多 ▾