From 146c1dac4526f1dc788ce535abb7c9108c36ba53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=88=98=E9=9F=B5=E7=90=B4?= <757188142@qq.com>
Date: Fri, 22 May 2026 08:35:04 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E8=90=A5=E5=85=BB=E7=94=A8=E9=A4=90?=
=?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=A4=9A=E9=A1=B5=E9=9D=A2=E4=BA=A4=E4=BA=92?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=88=E6=95=B0=E6=8D=AE=E5=88=86=E6=9E=90?=
=?UTF-8?q?/=E6=A8=A1=E5=9E=8B=E7=AE=A1=E7=90=86/=E7=BB=88=E7=AB=AF/?=
=?UTF-8?q?=E9=A4=90=E7=BA=BF=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- din-data-nutri: 新增食堂切换栏、周选择器、餐品明细弹窗重构、二级弹窗表单样式
- din-data-benefit: 新增食堂切换栏、食材分类级联选择器、重置按钮,移除损耗原因列
- din-model-llm: 新增 API_KEY/API_URL 列,状态改为启用/停用,新增接入/编辑模型弹窗
- din-model-small: 新增「新增模型」弹窗
- din-terminal: 新增食堂切换栏,筛选栏/表格列精简,新增设备弹窗字段调整
- din-order-line: 三个 Tab 操作列移除「编辑」链接,仅保留「详情」
---
web-admin/nutrition/din-data-benefit.html | 138 ++++-
web-admin/nutrition/din-data-nutri.html | 662 ++++++++++++++++++----
web-admin/nutrition/din-model-llm.html | 101 +++-
web-admin/nutrition/din-model-small.html | 38 +-
web-admin/nutrition/din-order-line.html | 38 +-
web-admin/nutrition/din-terminal.html | 129 ++++-
web-admin/nutrition/doc/CHANGELOG.md | 40 ++
7 files changed, 953 insertions(+), 193 deletions(-)
diff --git a/web-admin/nutrition/din-data-benefit.html b/web-admin/nutrition/din-data-benefit.html
index ea5e139..90711ae 100644
--- a/web-admin/nutrition/din-data-benefit.html
+++ b/web-admin/nutrition/din-data-benefit.html
@@ -117,6 +117,15 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
.loss-bar__fill{height:100%;border-radius:9px;transition:width .4s;}
.loss-bar__val{width:60px;font-weight:500;}
.loss-tip{background:#FFF7E6;border:1px solid #FFE58F;border-radius:var(--radius-sm);padding:10px 14px;font-size:var(--font-sm);color:#D48806;margin-top:12px;display:flex;align-items:flex-start;gap:6px;}
+/* 页面信息栏 */
+.page-header-bar{display:flex;align-items:center;justify-content:space-between;background:#fff;border-radius:var(--radius-md);padding:16px 24px;margin-bottom:16px;box-shadow:var(--shadow-sm);}
+.page-header-bar__left{display:flex;align-items:center;gap:12px;}
+.page-header-bar__title{font-size:var(--font-lg);font-weight:700;color:var(--text-primary);}
+.page-header-bar__meta{font-size:var(--font-sm);color:var(--text-placeholder);}
+.page-header-bar__right{display:flex;align-items:center;gap:12px;}
+.page-header-bar__right label{font-size:var(--font-sm);color:var(--text-secondary);white-space:nowrap;}
+.page-header-bar__right .canteen-select{height:36px;border:2px solid var(--primary);border-radius:var(--radius-sm);padding:0 32px 0 14px;font-size:var(--font-sm);color:var(--primary);font-weight:500;outline:none;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%231890FF'/%3E%3C/svg%3E") no-repeat right 12px center;appearance:none;cursor:pointer;min-width:140px;}
+
/* 食材成本明细弹窗 */
.cost-header{display:flex;gap:24px;margin-bottom:16px;font-size:var(--font-sm);}
.cost-header span{color:var(--text-secondary);}
@@ -129,6 +138,21 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
.cost-summary{display:flex;justify-content:flex-end;gap:24px;padding:12px 16px;background:#FAFAFA;border-radius:0 0 var(--radius-md) var(--radius-md);font-size:var(--font-sm);}
.cost-summary span{color:var(--text-secondary);}
.cost-summary strong{color:var(--primary);margin-left:4px;}
+/* 级联选择器 */
+.cascade-picker{position:relative;}
+.cascade-trigger{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 12px;font-size:var(--font-sm);background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;cursor:pointer;display:flex;align-items:center;white-space:nowrap;color:var(--text-placeholder);min-width:120px;}
+.cascade-trigger.has-value{color:var(--text-primary);}
+.cascade-panel{display:none;position:fixed;z-index:200;background:#fff;border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);width:320px;}
+.cascade-panel.show{display:flex;}
+.cascade-col{width:50%;max-height:240px;overflow-y:auto;}
+.cascade-col+.cascade-col{border-left:1px solid #f0f0f0;}
+.cascade-col__title{font-size:var(--font-xs);color:var(--text-placeholder);padding:8px 12px;border-bottom:1px solid #f0f0f0;position:sticky;top:0;background:#fff;}
+.cascade-opt{padding:7px 12px;font-size:var(--font-xs);cursor:pointer;transition:background .15s;display:flex;align-items:center;justify-content:space-between;}
+.cascade-opt:hover{background:#F8FBFF;}
+.cascade-opt.active{background:var(--primary-light);color:var(--primary);font-weight:500;}
+.cascade-opt .arrow-r{font-size:10px;color:var(--text-placeholder);}
+/* 重置按钮 */
+.btn-reset{background:#fff;color:var(--text-secondary);border:1px solid var(--border);}.btn-reset:hover{color:var(--danger);border-color:var(--danger);}
@@ -196,9 +220,25 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
+
+
+
-
+
@@ -217,11 +257,20 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
-
+
+
@@ -233,14 +282,14 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
- | 统计日期 | 食材编号 | 食材名称 | 所属分类 | 供应商 | 采购量(kg) | 采购单价(元/kg) | 采购总金额 | 实际使用量(kg) | 损耗量(kg) | 损耗金额 | 损耗率 | 预警等级 | 损耗原因 | 操作 |
+ | 统计日期 | 食材编号 | 食材名称 | 所属分类 | 供应商 | 采购量(kg) | 采购单价(元/kg) | 采购总金额 | 实际使用量(kg) | 损耗量(kg) | 损耗金额 | 损耗率 | 预警等级 | 操作 |
- | 2026-04-22 | ING-001 | 大白菜 | 蔬菜类 | 绿源农业 | 620 | ¥1.8 | ¥1,116 | 605 | 15 | ¥27 | 2.4% | 低 | 加工损耗 | 损耗明细 |
- | 2026-04-22 | ING-002 | 菠菜 | 蔬菜类 | 绿源农业 | 380 | ¥2.5 | ¥950 | 345 | 35 | ¥87.5 | 9.2% | 中 | 储存变质 | 损耗明细 |
- | 2026-04-21 | ING-003 | 猪肉(五花) | 肉禽类 | 旺旺肉业 | 480 | ¥26 | ¥12,480 | 462 | 18 | ¥468 | 3.8% | 低 | 加工损耗 | 损耗明细 |
- | 2026-04-21 | ING-004 | 鸡胸肉 | 肉禽类 | 旺旺肉业 | 320 | ¥20 | ¥6,400 | 308 | 12 | ¥240 | 3.8% | 低 | 加工损耗 | 损耗明细 |
- | 2026-04-20 | ING-005 | 鲫鱼 | 水产类 | 东海水产 | 280 | ¥24 | ¥6,720 | 248 | 32 | ¥768 | 11.4% | 高 | 过期未用 | 损耗明细 |
- | 2026-04-20 | ING-006 | 虾仁 | 水产类 | 东海水产 | 120 | ¥68 | ¥8,160 | 116 | 4 | ¥272 | 3.3% | 低 | 加工损耗 | 损耗明细 |
+ | 2026-04-22 | ING-001 | 大白菜 | 蔬菜类 | 绿源农业 | 620 | ¥1.8 | ¥1,116 | 605 | 15 | ¥27 | 2.4% | 低 | 损耗明细 |
+ | 2026-04-22 | ING-002 | 菠菜 | 蔬菜类 | 绿源农业 | 380 | ¥2.5 | ¥950 | 345 | 35 | ¥87.5 | 9.2% | 中 | 损耗明细 |
+ | 2026-04-21 | ING-003 | 猪肉(五花) | 肉禽类 | 旺旺肉业 | 480 | ¥26 | ¥12,480 | 462 | 18 | ¥468 | 3.8% | 低 | 损耗明细 |
+ | 2026-04-21 | ING-004 | 鸡胸肉 | 肉禽类 | 旺旺肉业 | 320 | ¥20 | ¥6,400 | 308 | 12 | ¥240 | 3.8% | 低 | 损耗明细 |
+ | 2026-04-20 | ING-005 | 鲫鱼 | 水产类 | 东海水产 | 280 | ¥24 | ¥6,720 | 248 | 32 | ¥768 | 11.4% | 高 | 损耗明细 |
+ | 2026-04-20 | ING-006 | 虾仁 | 水产类 | 东海水产 | 120 | ¥68 | ¥8,160 | 116 | 4 | ¥272 | 3.3% | 低 | 损耗明细 |
@@ -257,6 +306,7 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
+
@@ -296,7 +346,6 @@ const Modal={
overlay.innerHTML=``;
document.body.appendChild(overlay);
overlay.addEventListener('click',e=>{if(e.target===overlay)Modal.close();});
@@ -311,7 +360,7 @@ const Modal={
};
/* ===== 损耗明细弹窗 ===== */
-function showLossDetail(row){
+function showLossDetail(row,reasonText){
/* 从表格行中读取数据 */
const cells=row.querySelectorAll('td');
const date=cells[0].textContent.trim();
@@ -327,7 +376,7 @@ function showLossDetail(row){
const lossAmt=cells[10].textContent.trim();
const lossRate=cells[11].textContent.trim();
const level=cells[12].textContent.trim();
- const reason=cells[13].textContent.trim();
+ const reason=reasonText||'';
const html=`
@@ -351,10 +400,8 @@ function showLossDetail(row){
损耗金额${lossAmt}
损耗率${lossRate}
预警等级${level}
-
损耗原因${reason}
-
- ⚠️ 建议:${reason==='过期未用'?'加强库存先进先出管理,缩短采购周期,减少积压。':reason==='储存变质'?'检查冷链温控设备,优化储存条件,缩短库存周转天数。':'优化加工切配流程,加强厨师技能培训,减少边角料浪费。'}
`;
+ `;
Modal.open('损耗明细 — '+name,html);
}
@@ -430,7 +477,7 @@ document.querySelectorAll('.tab-panel').forEach((panel,tabIdx)=>{
panel.querySelectorAll('tbody tr').forEach(row=>{
row.querySelectorAll('.td-actions .link').forEach(link=>{
if(tabIdx===0 && link.textContent.includes('损耗明细')){
- link.addEventListener('click',()=>showLossDetail(row));
+ link.addEventListener('click',()=>showLossDetail(row,link.getAttribute('data-reason')||''));
}
if(tabIdx===1 && link.textContent.includes('食材成本明细')){
link.addEventListener('click',()=>showCostDetail(row));
@@ -438,6 +485,65 @@ document.querySelectorAll('.tab-panel').forEach((panel,tabIdx)=>{
});
});
});
+
+/* ===== 食材分类级联选择器 ===== */
+var BENEFIT_CATEGORIES={'蔬菜类':['叶菜类','根茎类','瓜果类','菌菇类','豆荚类'],'肉禽类':['猪肉','牛肉','羊肉','鸡肉','鸭肉'],'水产类':['淡水鱼','海水鱼','虾蟹','贝类'],'蛋类':['鸡蛋','鸭蛋','鹅蛋'],'豆制品类':['大豆','豆腐','豆浆'],'粮油类':['大米','面粉','食用油'],'调味品类':['酱料','香辛料','调味汁']};
+var benefitL1Active='';
+function toggleBenefitCascade(){
+ var panel=document.getElementById('benefitCascadePanel');
+ var open=!panel.classList.contains('show');
+ if(open){
+ var rect=document.getElementById('benefitCascadeTrigger').getBoundingClientRect();
+ panel.style.left=rect.left+'px';
+ panel.style.top=(rect.bottom+4)+'px';
+ benefitL1Active='';renderBenefitL1();document.getElementById('benefitCascadeL2').innerHTML='';
+ }
+ panel.classList.toggle('show',open);
+}
+function renderBenefitL1(){
+ var col=document.getElementById('benefitCascadeL1');
+ var html='一级分类
';
+ html+='全部分类
';
+ for(var k in BENEFIT_CATEGORIES){html+=''+k+'›
';}
+ col.innerHTML=html;
+}
+function renderBenefitL2(l1){
+ var col=document.getElementById('benefitCascadeL2');
+ if(!l1){col.innerHTML='';return;}
+ var subs=BENEFIT_CATEGORIES[l1]||[];
+ var html='二级分类
';
+ html+='全部'+l1+'
';
+ subs.forEach(function(s){html+=''+s+'
';});
+ col.innerHTML=html;
+}
+function hoverBenefitL1(l1){
+ benefitL1Active=l1;
+ document.querySelectorAll('#benefitCascadeL1 .cascade-opt').forEach(function(el,i){
+ if(i===0) el.classList.toggle('active',!l1);
+ else el.classList.toggle('active',el.textContent.replace('›','').trim()===l1);
+ });
+ renderBenefitL2(l1);
+}
+function selectBenefitCascade(l1,l2){
+ var trig=document.getElementById('benefitCascadeTrigger');
+ if(!l1){trig.textContent='全部';trig.classList.remove('has-value');}
+ else if(!l2){trig.textContent=l1;trig.classList.add('has-value');}
+ else{trig.textContent=l1+' / '+l2;trig.classList.add('has-value');}
+ document.getElementById('benefitCascadePanel').classList.remove('show');
+}
+document.addEventListener('click',function(e){if(!e.target.closest('#benefitCategoryPicker'))document.getElementById('benefitCascadePanel').classList.remove('show');});
+
+/* ===== 重置筛选 ===== */
+function resetFilter(tabIdx){
+ var panel=document.querySelectorAll('.tab-panel')[tabIdx];
+ if(!panel)return;
+ panel.querySelectorAll('.filter-select').forEach(function(s){s.selectedIndex=0;});
+ panel.querySelectorAll('.filter-input[type="date"]').forEach(function(inp){inp.value='';});
+ if(tabIdx===0){
+ var trig=document.getElementById('benefitCascadeTrigger');
+ trig.textContent='全部';trig.classList.remove('has-value');
+ }
+}