feat: 优化营养模块净菜联动与小程序登录

This commit is contained in:
fengpu
2026-06-18 09:54:31 +08:00
parent e663b7e827
commit 14a80cb167
26 changed files with 1643 additions and 468 deletions
+61 -52
View File
@@ -268,11 +268,11 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<button class="dialog__close" onclick="closeIngredientDialog()"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>
</div>
<div class="dialog__body">
<div class="form-group"><label>食材<span class="required">*</span></label>
<div class="search-select" id="ingredientSearchSelect">
<input class="form-input" type="text" id="ingredientSearchInput" placeholder="搜索食材名称..." oninput="searchIngredient(this.value)" onfocus="showIngredientDropdown()">
<div class="search-select__dropdown" id="ingredientDropdown"></div>
<div class="form-row">
<div class="form-group"><label>食材名称<span class="required">*</span></label>
<select class="form-select" id="ingredientNameSelect" onchange="selectIngredient(this.value)"><option value="">请选择食材</option></select>
</div>
<div class="form-group"><label>净菜类型<span class="required">*</span></label><select class="form-select" id="ingredientNetType" disabled><option value="">请先选择食材</option></select></div>
</div>
<div class="form-row"><div class="form-group"><label>用量(g/份)<span class="required">*</span></label><input class="form-input" type="number" id="ingredientAmount" placeholder="请输入用量"></div><div class="form-group"><label>是否主料</label><select class="form-select" id="ingredientIsMain"><option>辅料</option><option>主料</option></select></div></div>
<div class="form-row"><div class="form-group"><label>过敏原</label><input class="form-input" type="text" id="ingredientAllergen" placeholder="无则填无"></div><div class="form-group"><label>备注</label><input class="form-input" type="text" id="ingredientNote" placeholder="请输入备注信息"></div></div>
@@ -286,7 +286,11 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<script>
function toggleSubgroup(header){header.parentElement.classList.toggle('open');}
function openIngredientDialog(){document.getElementById('ingredientDialog').classList.add('open');}
function openIngredientDialog(){
initIngredientNameOptions();
resetIngredientForm();
document.getElementById('ingredientDialog').classList.add('open');
}
function closeIngredientDialog(){document.getElementById('ingredientDialog').classList.remove('open');}
var urlParams = new URLSearchParams(window.location.search);
@@ -298,9 +302,9 @@ var INNOV_MAP = {
expNo:'INN-H002', goal:'添加燕麦、藜麦,膳食纤维提升3倍', members:'厨师长陈磊 / 营养师王芳',
name:'高纤维主食包', category:'主食', meal:'早/午', pyramid:'谷薯杂豆', allergen:'无', tag:'高纤维',
composition:[
{name:'燕麦',cat:'谷薯类',amount:80,pct:'40%',main:true,allergen:'无',note:'提升纤维'},
{name:'藜麦',cat:'谷薯类',amount:60,pct:'30%',main:true,allergen:'无',note:'低GI'},
{name:'大米',cat:'谷薯类/稻米',amount:60,pct:'30%',main:false,allergen:'无',note:'基底'}
{name:'燕麦',netType:'燕麦片',amount:80,pct:'40%',main:true,allergen:'无',note:'提升纤维'},
{name:'藜麦',netType:'藜麦粒',amount:60,pct:'30%',main:true,allergen:'无',note:'低GI'},
{name:'大米',netType:'熟米饭',amount:60,pct:'30%',main:false,allergen:'无',note:'基底'}
],
cook:{mainMethod:'蒸',subMethod:'无',heat:'大火→中火',duration:30,oil:0,salt:3,temp:100,output:200,steps:4,desc:''},
nutri:{calorie:342,protein:12.8,carb:58.4,fat:5.2,vitC:0,mineral:38,fiber:9.6,sodium:210},
@@ -313,10 +317,10 @@ var INNOV_MAP = {
expNo:'INN-H004', goal:'搭配维C食材,补铁效率提升2倍', members:'厨师长赵敏 / 营养师李明',
name:'富铁青菜汤', category:'汤品', meal:'午/晚', pyramid:'蔬菜', allergen:'大豆', tag:'高铁',
composition:[
{name:'菠菜',cat:'蔬菜类',amount:120,pct:'40%',main:true,allergen:'无',note:'高铁来源'},
{name:'豆腐',cat:'豆制品',amount:80,pct:'27%',main:true,allergen:'大豆',note:'补充蛋白'},
{name:'胡萝卜',cat:'蔬菜类',amount:40,pct:'13%',main:false,allergen:'无',note:'维C协同'},
{name:'食用油',cat:'油脂类',amount:5,pct:'2%',main:false,allergen:'无',note:'少量'}
{name:'菠菜',netType:'菠菜段',amount:120,pct:'40%',main:true,allergen:'无',note:'高铁来源'},
{name:'豆腐',netType:'豆腐块',amount:80,pct:'27%',main:true,allergen:'大豆',note:'补充蛋白'},
{name:'胡萝卜',netType:'胡萝卜丝',amount:40,pct:'13%',main:false,allergen:'无',note:'维C协同'},
{name:'食用油',netType:'油',amount:5,pct:'2%',main:false,allergen:'无',note:'少量'}
],
cook:{mainMethod:'煮',subMethod:'无',heat:'大火→小火',duration:15,oil:5,salt:2,temp:100,output:300,steps:3,desc:''},
nutri:{calorie:68,protein:5.4,carb:6.2,fat:2.8,vitC:32,mineral:86,fiber:2.4,sodium:320},
@@ -390,7 +394,7 @@ var STEP_HTML = [
<button class="btn btn-primary" style="height:30px;font-size:var(--font-xs);" onclick="openIngredientDialog()"> 新增食材</button>
</div>
<table class="ingredient-table">
<thead><tr><th>食材名称</th><th>食材分类</th><th>用量(g/份)</th><th>是否主料</th><th>过敏原</th><th>备注</th><th>操作</th></tr></thead>
<thead><tr><th>食材名称</th><th>净菜类型</th><th>用量(g/份)</th><th>是否主料</th><th>过敏原</th><th>备注</th><th>操作</th></tr></thead>
<tbody><tr><td colspan="7" style="text-align:center;color:var(--text-placeholder);padding:32px;">暂无食材,请点击"新增食材"添加</td></tr></tbody>
</table>`,
@@ -539,67 +543,72 @@ function removeSpec(btn){
/* 食材搜索选择 */
var INGREDIENT_LIST=[
{name:'猪五花肉',cat:'畜禽肉类/猪肉'},{name:'猪里脊肉',cat:'畜禽肉类/猪肉'},{name:'牛腩',cat:'畜禽肉类/牛肉'},{name:'鸡胸肉',cat:'畜禽肉类/鸡肉'},{name:'鸡蛋',cat:'蛋类'},
{name:'番茄',cat:'蔬菜类/叶菜类'},{name:'菠菜',cat:'蔬菜类'},{name:'土豆',cat:'蔬菜类'},{name:'胡萝卜',cat:'蔬菜类'},{name:'大白菜',cat:'蔬菜类'},
{name:'大米',cat:'谷薯类/稻米'},{name:'面粉',cat:'谷薯类'},{name:'豆腐',cat:'豆制品'},{name:'食用油',cat:'油脂类'},{name:'生姜',cat:'调料'},
{name:'大蒜',cat:'调料'},{name:'生抽',cat:'调料'},{name:'食盐',cat:'调料'},{name:'白糖',cat:'调料'},{name:'料酒',cat:'调料'}
{name:'猪五花肉',types:['红烧块','五花片']},{name:'猪里脊肉',types:['里脊丝','里脊片']},{name:'牛腩',types:['牛腩块']},{name:'鸡胸肉',types:['鸡丁','鸡丝']},{name:'鸡蛋',types:['鸡蛋液','鸡蛋块']},
{name:'番茄',types:['番茄块','番茄丁']},{name:'菠菜',types:['菠菜段','菠菜泥']},{name:'土豆',types:['土豆丝','土豆块','土豆泥']},{name:'胡萝卜',types:['胡萝卜丝','胡萝卜块']},{name:'大白菜',types:['白菜帮','白菜叶']},
{name:'大米',types:['熟米饭','米粒']},{name:'面粉',types:['面粉糊']},{name:'豆腐',types:['豆腐块','豆腐丁']},{name:'食用油',types:['净油']},{name:'生姜',types:['姜丝','姜片']},
{name:'大蒜',types:['蒜末','蒜片']},{name:'生抽',types:['调味汁']},{name:'食盐',types:['盐粒']},{name:'白糖',types:['糖浆']},{name:'料酒',types:['料酒汁']}
];
function searchIngredient(keyword){
var dropdown=document.getElementById('ingredientDropdown');
if(!keyword.trim()){dropdown.classList.remove('show');return;}
var results=INGREDIENT_LIST.filter(function(item){return item.name.indexOf(keyword)!==-1;});
if(results.length===0){
dropdown.innerHTML='<div class="search-select__empty">未找到匹配食材</div>';
} else {
dropdown.innerHTML=results.map(function(item){
return '<div class="search-select__item" onclick="selectIngredient(\''+item.name+'\')"><span>'+item.name+'</span><span class="search-select__item-sub">'+item.cat+'</span></div>';
}).join('');
}
dropdown.classList.add('show');
function initIngredientNameOptions(){
var nameSelect=document.getElementById('ingredientNameSelect');
if(!nameSelect) return;
nameSelect.innerHTML='<option value="">请选择食材</option>'+INGREDIENT_LIST.map(function(item){
return '<option value="'+item.name+'">'+item.name+'</option>';
}).join('');
}
function showIngredientDropdown(){
var val=document.getElementById('ingredientSearchInput').value;
if(val.trim()) searchIngredient(val);
function resetIngredientForm(){
var nameSelect=document.getElementById('ingredientNameSelect');
if(nameSelect) nameSelect.value='';
var netTypeSelect=document.getElementById('ingredientNetType');
if(netTypeSelect){
netTypeSelect.innerHTML='<option value="">请先选择食材</option>';
netTypeSelect.disabled=true;
}
document.getElementById('ingredientAmount').value='';
document.getElementById('ingredientIsMain').selectedIndex=0;
document.getElementById('ingredientAllergen').value='';
document.getElementById('ingredientNote').value='';
}
function selectIngredient(name){
document.getElementById('ingredientSearchInput').value=name;
document.getElementById('ingredientDropdown').classList.remove('show');
var nameSelect=document.getElementById('ingredientNameSelect');
if(nameSelect) nameSelect.value=name;
var match=INGREDIENT_LIST.find(function(item){return item.name===name;});
var netTypeSelect=document.getElementById('ingredientNetType');
if(netTypeSelect){
netTypeSelect.innerHTML='';
if(match && match.types && match.types.length){
netTypeSelect.disabled=false;
netTypeSelect.innerHTML=match.types.map(function(type){return '<option value="'+type+'">'+type+'</option>';}).join('');
} else {
netTypeSelect.disabled=true;
netTypeSelect.innerHTML='<option value="">暂无净菜类型</option>';
}
}
}
function confirmAddIngredient(){
var name=document.getElementById('ingredientSearchInput').value.trim();
var name=document.getElementById('ingredientNameSelect').value.trim();
var netType=document.getElementById('ingredientNetType').value.trim();
var amount=document.getElementById('ingredientAmount').value.trim();
if(!name){alert('请选择食材');return;}
if(!netType){alert('请选择净菜类型');return;}
if(!amount){alert('请填写用量');return;}
var isMain=document.getElementById('ingredientIsMain').value;
var allergen=document.getElementById('ingredientAllergen').value.trim()||'无';
var note=document.getElementById('ingredientNote').value.trim()||'—';
var match=INGREDIENT_LIST.find(function(item){return item.name===name;});
var cat=match?match.cat:'—';
var tbody=document.querySelector('.ingredient-table tbody');
/* 移除空状态行 */
var emptyRow=tbody.querySelector('td[colspan]');
if(emptyRow) emptyRow.parentElement.remove();
var tr=document.createElement('tr');
tr.innerHTML='<td>'+name+'</td><td>'+cat+'</td><td>'+amount+'</td>'
tr.innerHTML='<td>'+name+'</td><td>'+netType+'</td><td>'+amount+'</td>'
+'<td>'+(isMain==='主料'?'<span class="tag tag-blue">主料</span>':'<span class="tag tag-gray">辅料</span>')+'</td>'
+'<td>'+allergen+'</td>'
+'<td>'+note+'</td>'
+'<td><a class="link" onclick="this.closest(\'tr\').remove()">删除</a></td>';
tbody.appendChild(tr);
/* 重置表单 */
document.getElementById('ingredientSearchInput').value='';
document.getElementById('ingredientAmount').value='';
document.getElementById('ingredientIsMain').selectedIndex=0;
document.getElementById('ingredientAllergen').value='';
document.getElementById('ingredientNote').value='';
resetIngredientForm();
closeIngredientDialog();
}
document.addEventListener('click',function(e){
if(!e.target.closest('#ingredientSearchSelect')){
var dd=document.getElementById('ingredientDropdown');
if(dd) dd.classList.remove('show');
}
});
/* 图片上传 */
function triggerImageUpload(){
@@ -669,7 +678,7 @@ var EDIT_DATA = {
allergen:'无', tag:'高蛋白', status:'上架',
crowd:[{name:'成人',level:'推荐'},{name:'高血脂人群',level:'慎食'},{name:'高血压人群',level:'适量'}],
specs:[{spec:'标准份',weight:200,price:12,isDefault:true},{spec:'小份',weight:120,price:8,isDefault:false},{spec:'大份',weight:300,price:18,isDefault:false}],
composition:[{name:'五花肉',amount:150,pct:'60%',main:true,allergen:'无',note:'—'},{name:'冰糖',amount:20,pct:'8%',main:false,allergen:'无',note:'上色'},{name:'酱油',amount:15,pct:'6%',main:false,allergen:'含大豆',note:'调味'},{name:'料酒',amount:10,pct:'4%',main:false,allergen:'无',note:'去腥'}],
composition:[{name:'五花肉',netType:'红烧块',amount:150,pct:'60%',main:true,allergen:'无',note:'—'},{name:'冰糖',netType:'糖浆',amount:20,pct:'8%',main:false,allergen:'无',note:'上色'},{name:'酱油',netType:'调味汁',amount:15,pct:'6%',main:false,allergen:'含大豆',note:'调味'},{name:'料酒',netType:'料酒汁',amount:10,pct:'4%',main:false,allergen:'无',note:'去腥'}],
cook:{mainMethod:'炖',subMethod:'煎',heat:'中火→小火',duration:45,oil:15,salt:3,temp:100,output:200,steps:6,desc:'1.五花肉切块焯水;2.锅中煎至金黄;3.加冰糖炒色;4.加酱油料酒;5.加水小火炖40分钟;6.大火收汁'},
nutri:{calorie:385,protein:18.2,carb:12.4,fat:28.6,vitC:2.1,mineral:45,fiber:1.8,sodium:486},
taste:{sour:1,sweet:3,bitter:1,spicy:1,salty:4,smell:4.2,flavorScore:3.8,flavorGrade:'good'},
@@ -764,8 +773,8 @@ function fillEditData(){
d.composition.forEach(function(c){
var tr = document.createElement('tr');
tr.innerHTML = (pageMode==='convert'
? '<td>'+c.name+'</td><td>'+c.amount+'g</td><td>'+c.pct+'</td><td><span class="tag tag-'+(c.main?'green':'gray')+'">'+(c.main?'主料':'辅料')+'</span></td><td>'+c.allergen+'</td><td>'+c.note+'</td><td><span style="color:#bbb;cursor:not-allowed;">编辑</span> <span style="color:#bbb;cursor:not-allowed;">删除</span></td>'
: '<td>'+c.name+'</td><td>'+c.amount+'g</td><td>'+c.pct+'</td><td><span class="tag tag-'+(c.main?'green':'gray')+'">'+(c.main?'主料':'辅料')+'</span></td><td>'+c.allergen+'</td><td>'+c.note+'</td><td><span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td>');
? '<td>'+c.name+'</td><td>'+(c.netType||'—')+'</td><td>'+c.amount+'g</td><td><span class="tag tag-'+(c.main?'green':'gray')+'">'+(c.main?'主料':'辅料')+'</span></td><td>'+c.allergen+'</td><td>'+c.note+'</td><td><span style="color:#bbb;cursor:not-allowed;">编辑</span> <span style="color:#bbb;cursor:not-allowed;">删除</span></td>'
: '<td>'+c.name+'</td><td>'+(c.netType||'—')+'</td><td>'+c.amount+'g</td><td><span class="tag tag-'+(c.main?'green':'gray')+'">'+(c.main?'主料':'辅料')+'</span></td><td>'+c.allergen+'</td><td>'+c.note+'</td><td><span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td>');
tbody.appendChild(tr);
});
}
+9 -9
View File
@@ -275,7 +275,7 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
// 餐品数据
const DISHES = [
{id:'DISH001',name:'红烧肉',icon:'🥩',category:'荤菜',tags:['高蛋白'],specs:[{name:'标准份',weight:200,price:12,isDefault:true},{name:'小份',weight:120,price:8},{name:'大份',weight:300,price:18}],method:'炖',meal:'午/晚',allergen:'无',status:'启用',source:'手动添加',weightBasePrice:'6.00',weightVipPrice:'5.40',crowd:[{name:'成人',level:'推荐'},{name:'高血脂人群',level:'慎食'},{name:'高血压人群',level:'适量'}],crowdNote:'高血脂人群控制摄入量',
composition:[{name:'猪五花肉',cat:'肉禽类/猪肉',amount:160,pct:'80%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'生姜',cat:'调味品/香辛料',amount:5,pct:'2.5%',state:'净菜',main:false,allergen:'无',note:'—'},{name:'生抽',cat:'调味品/酱油',amount:15,pct:'7.5%',state:'原料',main:false,allergen:'含麸质',note:'酱油'},{name:'冰糖',cat:'调味品/糖类',amount:10,pct:'5%',state:'原料',main:false,allergen:'无',note:'上色提味'},{name:'料酒',cat:'调味品/酒类',amount:10,pct:'5%',state:'原料',main:false,allergen:'无',note:'去腥'}],
composition:[{name:'猪五花肉',netType:'红烧块',amount:160,pct:'80%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'生姜',netType:'姜片',amount:5,pct:'2.5%',state:'净菜',main:false,allergen:'无',note:'—'},{name:'生抽',netType:'调味',amount:15,pct:'7.5%',state:'原料',main:false,allergen:'含麸质',note:'酱油'},{name:'冰糖',netType:'糖浆',amount:10,pct:'5%',state:'原料',main:false,allergen:'无',note:'上色提味'},{name:'料酒',netType:'料酒汁',amount:10,pct:'5%',state:'原料',main:false,allergen:'无',note:'去腥'}],
nutri:{calorie:385,protein:18.2,carb:12.4,fat:28.6,vitC:0.8,mineral:42,fiber:0.3,sodium:486,nutriGrade:'偏差',note:'铁2.4mg、锌1.8mg'},
cook:{mainMethod:'炖',subMethod:'煎',heat:'中火→小火',duration:45,oil:15,salt:3,temp:'100→80',output:200,steps:6},
taste:{sour:1,sweet:3,bitter:1,spicy:1,salty:4,smell:4.2,flavorScore:3.8,flavorGrade:'良好'},
@@ -283,7 +283,7 @@ const DISHES = [
texture:{hardness:2,sticky:3,crispy:1,smooth:4,elastic:3,textureScore:3.6,textureGrade:'良好'}
},
{id:'DISH002',name:'清炒时蔬',icon:'🥬',category:'素菜',tags:['低脂','素食'],specs:[{name:'标准份',weight:150,price:6,isDefault:true},{name:'小份',weight:100,price:4}],method:'炒',meal:'早/午/晚',allergen:'无',status:'启用',source:'系统内置',weightBasePrice:'3.00',weightVipPrice:'2.70',crowd:[{name:'全人群',level:'推荐'},{name:'糖尿病人群',level:'推荐'},{name:'肾结石人群',level:'慎食'}],crowdNote:'肾结石人群慎食(草酸含量高)',
composition:[{name:'时令青菜',cat:'蔬菜类/叶菜',amount:120,pct:'80%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'蒜末',cat:'调味品/香辛料',amount:5,pct:'3.3%',state:'净菜',main:false,allergen:'无',note:'—'},{name:'食用油',cat:'油脂类/植物油',amount:8,pct:'5.3%',state:'原料',main:false,allergen:'无',note:'—'},{name:'食盐',cat:'调味品/盐类',amount:2,pct:'1.3%',state:'原料',main:false,allergen:'无',note:'—'}],
composition:[{name:'时令青菜',netType:'青菜段',amount:120,pct:'80%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'蒜末',netType:'蒜末',amount:5,pct:'3.3%',state:'净菜',main:false,allergen:'无',note:'—'},{name:'食用油',netType:'油',amount:8,pct:'5.3%',state:'原料',main:false,allergen:'无',note:'—'},{name:'食盐',netType:'盐粒',amount:2,pct:'1.3%',state:'原料',main:false,allergen:'无',note:'—'}],
nutri:{calorie:68,protein:2.1,carb:8.6,fat:3.2,vitC:28.5,mineral:86,fiber:2.4,sodium:186,nutriGrade:'达标',note:'铁1.2mg、钙45mg'},
cook:{mainMethod:'炒',subMethod:'—',heat:'大火',duration:5,oil:8,salt:2,temp:'200',output:150,steps:4},
taste:{sour:1,sweet:2,bitter:1,spicy:1,salty:2,smell:3.5,flavorScore:3.2,flavorGrade:'一般'},
@@ -291,7 +291,7 @@ const DISHES = [
texture:{hardness:3,sticky:1,crispy:4,smooth:3,elastic:2,textureScore:3.4,textureGrade:'良好'}
},
{id:'DISH003',name:'番茄鸡蛋汤',icon:'🍅',category:'汤品',tags:['低卡'],specs:[{name:'标准份',weight:300,price:5,isDefault:true}],method:'煮',meal:'午/晚',allergen:'含蛋类',status:'启用',source:'系统内置',weightBasePrice:'1.67',weightVipPrice:'1.50',crowd:[{name:'全人群',level:'推荐'},{name:'儿童',level:'推荐'},{name:'老年人',level:'推荐'}],crowdNote:'',
composition:[{name:'番茄',cat:'蔬菜类/茄果',amount:150,pct:'50%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'鸡蛋',cat:'蛋类/禽蛋',amount:60,pct:'20%',state:'原料',main:true,allergen:'含蛋类',note:'—'},{name:'食用油',cat:'油脂类/植物油',amount:5,pct:'1.7%',state:'原料',main:false,allergen:'无',note:'—'},{name:'食盐',cat:'调味品/盐类',amount:2,pct:'0.7%',state:'原料',main:false,allergen:'无',note:'—'}],
composition:[{name:'番茄',netType:'番茄块',amount:150,pct:'50%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'鸡蛋',netType:'鸡蛋液',amount:60,pct:'20%',state:'原料',main:true,allergen:'含蛋类',note:'—'},{name:'食用油',netType:'油',amount:5,pct:'1.7%',state:'原料',main:false,allergen:'无',note:'—'},{name:'食盐',netType:'盐粒',amount:2,pct:'0.7%',state:'原料',main:false,allergen:'无',note:'—'}],
nutri:{calorie:45,protein:3.8,carb:4.2,fat:2.1,vitC:18.2,mineral:32,fiber:1.1,sodium:280,nutriGrade:'达标',note:'铁0.8mg、钾210mg'},
cook:{mainMethod:'煮',subMethod:'炒',heat:'中火',duration:12,oil:5,salt:2,temp:'100',output:300,steps:5},
taste:{sour:3,sweet:2,bitter:1,spicy:1,salty:2,smell:3.8,flavorScore:3.5,flavorGrade:'良好'},
@@ -299,7 +299,7 @@ const DISHES = [
texture:{hardness:1,sticky:2,crispy:1,smooth:5,elastic:2,textureScore:3.8,textureGrade:'良好'}
},
{id:'DISH004',name:'米饭',icon:'🍚',category:'主食',tags:['主食'],specs:[{name:'标准份',weight:200,price:3,isDefault:true},{name:'小份',weight:100,price:2},{name:'大份',weight:300,price:4}],method:'蒸',meal:'早/午/晚',allergen:'无',status:'启用',source:'系统内置',weightBasePrice:'1.50',weightVipPrice:'1.35',crowd:[{name:'全人群',level:'推荐'},{name:'糖尿病人群',level:'适量'}],crowdNote:'糖尿病人群注意控制量',
composition:[{name:'大米',cat:'谷薯类/稻米',amount:100,pct:'100%',state:'原料',main:true,allergen:'无',note:'—'}],
composition:[{name:'大米',netType:'熟米饭',amount:100,pct:'100%',state:'原料',main:true,allergen:'无',note:'—'}],
nutri:{calorie:232,protein:4.8,carb:51.2,fat:0.6,vitC:0,mineral:12,fiber:0.4,sodium:3,nutriGrade:'达标',note:'—'},
cook:{mainMethod:'蒸',subMethod:'—',heat:'大火→中火',duration:30,oil:0,salt:0,temp:'100',output:200,steps:2},
taste:{sour:1,sweet:2,bitter:1,spicy:1,salty:1,smell:3.0,flavorScore:2.8,flavorGrade:'一般'},
@@ -307,7 +307,7 @@ const DISHES = [
texture:{hardness:2,sticky:3,crispy:1,smooth:3,elastic:2,textureScore:3.2,textureGrade:'一般'}
},
{id:'DISH005',name:'糖醋里脊',icon:'🍖',category:'荤菜',tags:['高糖'],specs:[{name:'标准份',weight:180,price:14,isDefault:true},{name:'大份',weight:280,price:20}],method:'炸',meal:'午',allergen:'无',status:'停用',source:'味养创新',weightBasePrice:'7.78',weightVipPrice:'7.00',crowd:[{name:'成人',level:'推荐'},{name:'糖尿病人群',level:'慎食'},{name:'高血脂人群',level:'适量'}],crowdNote:'糖尿病人群慎食,含糖量高',
composition:[{name:'猪里脊肉',cat:'肉禽类/猪肉',amount:120,pct:'66.7%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'淀粉',cat:'谷薯类/淀粉',amount:20,pct:'11.1%',state:'原料',main:false,allergen:'无',note:'挂糊'},{name:'白糖',cat:'调味品/糖类',amount:25,pct:'13.9%',state:'原料',main:false,allergen:'无',note:'糖醋汁'},{name:'食醋',cat:'调味品/醋类',amount:15,pct:'8.3%',state:'原料',main:false,allergen:'无',note:'糖醋汁'}],
composition:[{name:'猪里脊肉',netType:'里脊丝',amount:120,pct:'66.7%',state:'净菜',main:true,allergen:'无',note:'—'},{name:'淀粉',netType:'淀粉',amount:20,pct:'11.1%',state:'原料',main:false,allergen:'无',note:'挂糊'},{name:'白糖',netType:'糖浆',amount:25,pct:'13.9%',state:'原料',main:false,allergen:'无',note:'糖醋汁'},{name:'食醋',netType:'调味',amount:15,pct:'8.3%',state:'原料',main:false,allergen:'无',note:'糖醋汁'}],
nutri:{calorie:420,protein:22.4,carb:38.2,fat:18.6,vitC:1.2,mineral:28,fiber:0.6,sodium:620,nutriGrade:'未达标',note:'铁1.8mg'},
cook:{mainMethod:'炸',subMethod:'炒',heat:'大火',duration:15,oil:50,salt:1,temp:'180',output:180,steps:7},
taste:{sour:4,sweet:4,bitter:1,spicy:1,salty:3,smell:4.0,flavorScore:4.2,flavorGrade:'良好'},
@@ -385,9 +385,9 @@ function renderBasic(d){
}
function renderComposition(d){
const rows = (d.composition||[]).map(c=>`<tr><td>${c.name}</td><td>${c.cat}</td><td>${c.amount}</td><td>${c.pct}</td><td><span class="tag tag-${c.main?'green':'gray'}">${c.main?'主料':'辅料'}</span></td><td>${c.allergen}</td><td>${c.note}</td></tr>`).join('');
const rows = (d.composition||[]).map(c=>`<tr><td>${c.name}</td><td>${c.netType}</td><td>${c.amount}</td><td>${c.pct}</td><td><span class="tag tag-${c.main?'green':'gray'}">${c.main?'主料':'辅料'}</span></td><td>${c.allergen}</td><td>${c.note}</td></tr>`).join('');
return `<div class="info-section"><div class="info-section__title">食材构成(共 ${(d.composition||[]).length} 项) <span><a class="link" href="din-dish-add.html?mode=edit&tab=1">编辑</a></span></div>
<table class="info-table"><thead><tr><th>食材名称</th><th>食材分类</th><th>用量(g/份)</th><th>占比(%)</th><th>是否主料</th><th>过敏原</th><th>备注</th></tr></thead><tbody>${rows}</tbody></table></div>`;
<table class="info-table"><thead><tr><th>食材名称</th><th>净菜类型</th><th>用量(g/份)</th><th>占比(%)</th><th>是否主料</th><th>过敏原</th><th>备注</th></tr></thead><tbody>${rows}</tbody></table></div>`;
}
function renderCook(d){
@@ -506,7 +506,7 @@ renderDetail();
<div class="dialog__body">
<div class="form-row">
<div class="form-group"><label>食材名称<span class="required">*</span></label><input class="form-input" type="text" placeholder="请输入食材名称"></div>
<div class="form-group"><label>食材分类<span class="required">*</span></label><select class="form-select"><option>请选择</option><option>畜肉类</option><option>禽肉类</option><option>蛋类</option><option>蔬菜类</option><option>谷薯类</option><option>油脂类</option><option>调料</option></select></div>
<div class="form-group"><label>净菜类型<span class="required">*</span></label><select class="form-select"><option>请选择</option><option>土豆丝</option><option>土豆块</option><option>土豆泥</option><option>番茄块</option><option>蒜末</option></select></div>
</div>
<div class="form-row">
<div class="form-group"><label>用量(g/份)<span class="required">*</span></label><input class="form-input" type="number" placeholder="请输入用量"></div>
@@ -530,4 +530,4 @@ function openIngredientDialog(){document.getElementById('ingredientDialog').clas
function closeIngredientDialog(){document.getElementById('ingredientDialog').classList.remove('open');}
</script>
</body>
</html>
</html>
+32 -23
View File
@@ -234,11 +234,8 @@ var STEP_HTML = [
<div class="form-group"><label class="form-label">水分(%)</label><input class="form-input" id="waterRate" placeholder="0~100"></div>
<div class="form-group"><label class="form-label">数据来源</label><select class="form-select" id="dataSource"><option value="1">手动添加</option></select></div>
<div class="form-group full"><label class="form-label">净菜类型</label>
<div class="tag-group" id="vegTypeGroup"></div>
<div class="tag-input-row">
<input class="form-input" id="vegTypeInput" placeholder="输入净菜类型名称">
<button type="button" class="btn btn-primary" onclick="addVegType()">添加</button>
</div>
<div class="dynamic-rows" id="vegTypeRows"></div>
<button type="button" class="dynamic-row-add" onclick="addVegType()">+ 添加净菜类型</button>
</div>
<div class="form-group"><label class="form-label">食材图片</label>
<div class="upload-box" id="uploadBox" onclick="triggerUpload()">
@@ -371,6 +368,7 @@ function saveCurrentStep(){
inputs.forEach(function(el){if(el.id) formData[el.id]=el.value;});
// 保存动态行数据
if(currentStep===0){
saveVegTypes();
var rows = document.querySelectorAll('#crowdRows .dynamic-row');
crowdList = [];
rows.forEach(function(row){
@@ -450,30 +448,41 @@ function submitForm(){
window.location.href='din-ingredient.html';
}
/* === 净菜类型 === */
/* === 净菜类型动态行 === */
function renderVegTypes(){
var group = document.getElementById('vegTypeGroup');
if(!group) return;
var container = document.getElementById('vegTypeRows');
if(!container) return;
if(vegTypes.length===0) vegTypes.push({name:'',yieldRate:''});
var html = '';
vegTypes.forEach(function(t,i){
html += '<span class="tag-item">'+t+'<span class="tag-item__del" onclick="removeVegType('+i+')">×</span></span>';
vegTypes.forEach(function(item,i){
html += '<div class="dynamic-row">';
html += '<input class="form-input veg-name" placeholder="净菜名称" value="'+(item.name||'')+'">';
html += '<input class="form-input veg-yield" type="number" min="0" max="100" placeholder="菜品出净率(0~100" value="'+(item.yieldRate||'')+'">';
html += '<button type="button" class="dynamic-row__del" onclick="removeVegType('+i+')" title="删除">×</button>';
html += '</div>';
});
group.innerHTML = html;
container.innerHTML = html;
}
function addVegType(){
var input = document.getElementById('vegTypeInput');
if(!input) return;
var val = input.value.trim();
if(val){
vegTypes.push(val);
input.value = '';
renderVegTypes();
}
saveVegTypes();
vegTypes.push({name:'',yieldRate:''});
renderVegTypes();
}
function removeVegType(idx){
saveVegTypes();
vegTypes.splice(idx,1);
if(vegTypes.length===0) vegTypes.push({name:'',yieldRate:''});
renderVegTypes();
}
function saveVegTypes(){
var rows = document.querySelectorAll('#vegTypeRows .dynamic-row');
vegTypes = [];
rows.forEach(function(row){
var name = row.querySelector('.veg-name');
var yieldRate = row.querySelector('.veg-yield');
if(name && yieldRate) vegTypes.push({name:name.value,yieldRate:yieldRate.value});
});
}
/* === 食物分类级联选择器 === */
var ADD_CATEGORIES={'谷薯类':['稻米','小麦','玉米','薯类','杂粮'],'畜禽肉类':['猪肉','牛肉','羊肉','鸡肉','鸭肉'],'水产类':['淡水鱼','海水鱼','虾蟹','贝类'],'蛋类':['鸡蛋','鸭蛋','鹅蛋','鹌鹑蛋'],'奶及奶制品':['牛奶','酸奶','奶酪','奶粉'],'豆及豆制品':['大豆','豆制品','杂豆'],'蔬菜类':['叶菜类','根茎类','瓜果类','菌菇类','豆荚类'],'水果类':['仁果类','浆果类','柑橘类','瓜果类','热带水果'],'坚果种子类':['坚果','种子'],'油脂类':['植物油','动物油'],'调味品类':['酱料','香辛料','调味汁']};
@@ -618,7 +627,7 @@ if(initTab >= 0 && initTab < totalSteps) currentStep = initTab;
/* 编辑模式 mock 数据(与 din-ingredient.html 的 FOODS 结构一致) */
var EDIT_FOODS = {
'0101001':{name:'粳米(生)',code:'0101001',alias:'大米',firstClass:'谷薯类',secondClass:'稻米',edible:'97',waterRate:'13.3',dataSource:'0',vegTypes:['洗净米','免淘米'],
'0101001':{name:'粳米(生)',code:'0101001',alias:'大米',firstClass:'谷薯类',secondClass:'稻米',edible:'97',waterRate:'13.3',dataSource:'0',vegTypes:[{name:'洗净米',yieldRate:'97'},{name:'免淘米',yieldRate:'95'}],
crowd:[{name:'全人群',level:'推荐'},{name:'糖尿病人群',level:'适量'}],
nutri:{calorie:346,protein:7.4,fat:0.6,carbohydrate:77.2,dietary_fiber:0.7,
vitamin_a:0,vitamin_b1:0.11,vitamin_b2:0.02,vitamin_b6:0.12,vitamin_b12:0,vitamin_c:0,vitamin_d:0,vitamin_e:1.01,vitamin_k:0,niacin:1.6,folic_acid:3.8,biotin:0,pantothenic_acid:0.6,total_choline:0,
@@ -629,7 +638,7 @@ var EDIT_FOODS = {
color:{main:'乳白色',grade:'优',desc:'色泽洁白,半透明,颗粒饱满',cause:'碾磨去皮后淀粉体暴露'},
taste:{main:'淡味',sub:'微涩',intensity:'弱',desc:'生米无明显味道,煮熟后清香'},
texture:{main:'软糯',chew:'易',digest:'中',desc:'米粒饱满,质地坚硬,煮后软糯',cook:'水米比1:1.2,浸泡30分钟口感更佳'}},
'0301001':{name:'猪里脊(生)',code:'0301001',alias:'里脊肉',firstClass:'畜禽肉类',secondClass:'猪肉',edible:'100',waterRate:'73.3',dataSource:'0',vegTypes:['去筋膜','切丁'],
'0301001':{name:'猪里脊(生)',code:'0301001',alias:'里脊肉',firstClass:'畜禽肉类',secondClass:'猪肉',edible:'100',waterRate:'73.3',dataSource:'0',vegTypes:[{name:'去筋膜',yieldRate:'92'},{name:'切丁',yieldRate:'88'}],
crowd:[{name:'成人',level:'推荐'},{name:'儿童',level:'推荐'},{name:'高血脂人群',level:'适量'}],
nutri:{calorie:143,protein:20.2,fat:7.1,carbohydrate:0.7,dietary_fiber:0,
vitamin_a:6,vitamin_b1:0.54,vitamin_b2:0.1,vitamin_b6:0.27,vitamin_b12:0.6,vitamin_c:0,vitamin_d:0.2,vitamin_e:0.34,vitamin_k:0,niacin:5.3,folic_acid:5,biotin:0,pantothenic_acid:0.5,total_choline:0,
@@ -651,7 +660,7 @@ var EDIT_FOODS = {
color:{main:'金黄色',grade:'优',desc:'蛋壳浅褐,蛋黄金黄饱满',cause:'蛋黄富含叶黄素和类胡萝卜素'},
taste:{main:'鲜味',sub:'蛋香',intensity:'中',desc:'蛋白柔和,蛋黄浓郁'},
texture:{main:'嫩滑',chew:'易',digest:'易',desc:'水煮蛋弹嫩,炒蛋软嫩,蒸蛋细腻',cook:'蒸蛋口感最软,适合各年龄段'}},
'0201001':{name:'菠菜(生)',code:'0201001',alias:'波斯菜',firstClass:'蔬菜类',secondClass:'叶菜类',edible:'89',waterRate:'91.2',dataSource:'0',vegTypes:['去根','切段'],
'0201001':{name:'菠菜(生)',code:'0201001',alias:'波斯菜',firstClass:'蔬菜类',secondClass:'叶菜类',edible:'89',waterRate:'91.2',dataSource:'0',vegTypes:[{name:'去根',yieldRate:'90'},{name:'切段',yieldRate:'88'}],
crowd:[{name:'全人群',level:'推荐'},{name:'肾结石人群',level:'慎食'}],
nutri:{calorie:28,protein:2.6,fat:0.3,carbohydrate:4.5,dietary_fiber:1.7,
vitamin_a:487,vitamin_b1:0.04,vitamin_b2:0.11,vitamin_b6:0.1,vitamin_b12:0,vitamin_c:32,vitamin_d:0,vitamin_e:1.74,vitamin_k:0,niacin:0.6,folic_acid:110,biotin:0,pantothenic_acid:0.2,total_choline:0,
@@ -662,7 +671,7 @@ var EDIT_FOODS = {
color:{main:'深绿色',grade:'优',desc:'叶片翠绿有光泽,根部紫红',cause:'叶绿素含量高'},
taste:{main:'清甜',sub:'微涩',intensity:'弱',desc:'清爽微甜带涩'},
texture:{main:'嫩脆',chew:'易',digest:'易',desc:'叶片嫩滑,茎部脆嫩',cook:'焯水去草酸后口感最佳'}},
'0601001':{name:'豆腐(北)',code:'0601001',alias:'北豆腐',firstClass:'豆及豆制品',secondClass:'豆制品',edible:'100',waterRate:'82.8',dataSource:'1',vegTypes:['切块','切丁'],
'0601001':{name:'豆腐(北)',code:'0601001',alias:'北豆腐',firstClass:'豆及豆制品',secondClass:'豆制品',edible:'100',waterRate:'82.8',dataSource:'1',vegTypes:[{name:'切块',yieldRate:'96'},{name:'切丁',yieldRate:'94'}],
crowd:[{name:'全人群',level:'推荐'},{name:'高血压人群',level:'推荐'},{name:'痛风人群',level:'适量'},{name:'老年人',level:'推荐'},{name:'术后恢复',level:'推荐'}],
nutri:{calorie:98,protein:12.2,fat:4.8,carbohydrate:1.5,dietary_fiber:0.4,
vitamin_a:0,vitamin_b1:0.07,vitamin_b2:0.04,vitamin_b6:0.05,vitamin_b12:0,vitamin_c:0,vitamin_d:0,vitamin_e:2.71,vitamin_k:0,niacin:0.1,folic_acid:37,biotin:0,pantothenic_acid:0.1,total_choline:0,
+17 -5
View File
@@ -119,6 +119,12 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
.profile-field__label{font-size:var(--font-xs);color:var(--text-placeholder);}
.profile-field__value{font-size:var(--font-sm);color:var(--text-primary);line-height:1.5;}
.profile-field--full{grid-column:1/-1;}
/* 净菜类型小表格 */
.veg-type-table{width:100%;border-collapse:collapse;border:1px solid #F0F0F0;border-radius:var(--radius-sm);overflow:hidden;margin-top:4px;}
.veg-type-table th{background:#FAFAFA;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;text-align:left;padding:8px 12px;border-bottom:1px solid #F0F0F0;}
.veg-type-table td{font-size:var(--font-sm);color:var(--text-primary);padding:8px 12px;border-bottom:1px solid #F5F5F5;}
.veg-type-table tr:last-child td{border-bottom:none;}
.veg-type-table th+th,.veg-type-table td+td{border-left:1px solid #F0F0F0;}
/* 级联选择器 */
.cascade-picker{position:relative;flex:1;}
.cascade-trigger{height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 28px 0 10px;font-size:var(--font-xs);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 8px center;cursor:pointer;display:flex;align-items:center;white-space:nowrap;color:var(--text-placeholder);width:100%;}
@@ -297,7 +303,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<script>
// 食物数据(对齐 yx_mater_base_material 表结构)
const FOODS = [
{name:'粳米(生)',code:'0101001',alias:'大米',firstClass:'谷薯类',secondClass:'稻米',icon:'🌾',edible:'100',waterRate:'13.3',dataSource:0,vegTypes:['洗净米','免淘米'],
{name:'粳米(生)',code:'0101001',alias:'大米',firstClass:'谷薯类',secondClass:'稻米',icon:'🌾',edible:'100',waterRate:'13.3',dataSource:0,vegTypes:[{name:'洗净米',yieldRate:'97'},{name:'免淘米',yieldRate:'95'}],
nutri:{calorie:346,protein:7.4,fat:0.8,carbohydrate:77.2,dietary_fiber:0.6,
vitamin_a:0,vitamin_b1:0.16,vitamin_b2:0.08,vitamin_b6:0.16,vitamin_b12:0,vitamin_c:0,vitamin_d:0,vitamin_e:0.46,vitamin_k:0,niacin:1.9,folic_acid:3.8,biotin:0,pantothenic_acid:0.6,total_choline:0,
ca:13,phosphorus:110,kalium:103,mg:34,na:3.8,fe:2.3,zn:1.7,se:2.23,cu:0.3,mn:1.29,iodine:0,
@@ -307,7 +313,7 @@ const FOODS = [
color:{main:'白色',desc:'乳白色,半透明,颗粒饱满',cause:'淀粉主体,含少量蛋白质',grade:'优',crowd:[{name:'成人',level:'推荐'},{name:'老年人',level:'推荐'},{name:'儿童',level:'推荐'}],note:'—'},
taste:{main:'淡味',sub:'—',intensity:'弱',desc:'清淡,煮熟后微甜,无异味',crowd:[{name:'全人群',level:'推荐'},{name:'糖尿病人群',level:'适量'}],note:'糖尿病人群注意控制量'},
texture:{main:'软糯',chew:'易',digest:'易',desc:'煮熟后软糯有嚼劲,易于消化',crowd:[{name:'全人群',level:'推荐'},{name:'老年人',level:'推荐'},{name:'术后恢复',level:'推荐'}],cook:'熬粥质地更软,适合老年人'}},
{name:'猪里脊肉',code:'0201001',alias:'里脊',firstClass:'畜禽肉类',secondClass:'猪肉',icon:'🥩',edible:'100',waterRate:'71.4',dataSource:0,vegTypes:['肉片','肉丁','肉块'],
{name:'猪里脊肉',code:'0201001',alias:'里脊',firstClass:'畜禽肉类',secondClass:'猪肉',icon:'🥩',edible:'100',waterRate:'71.4',dataSource:0,vegTypes:[{name:'肉片',yieldRate:'95'},{name:'肉丁',yieldRate:'92'},{name:'肉块',yieldRate:'97'}],
nutri:{calorie:155,protein:20.2,fat:7.9,carbohydrate:0.7,dietary_fiber:0,
vitamin_a:6,vitamin_b1:0.54,vitamin_b2:0.1,vitamin_b6:0.33,vitamin_b12:0.6,vitamin_c:0,vitamin_d:0,vitamin_e:0.34,vitamin_k:0,niacin:5.3,folic_acid:3,biotin:0,pantothenic_acid:0.8,total_choline:0,
ca:6,phosphorus:196,kalium:305,mg:25,na:43.2,fe:1.5,zn:2.3,se:11.97,cu:0.09,mn:0.01,iodine:0,
@@ -337,7 +343,7 @@ const FOODS = [
color:{main:'米黄色',desc:'蛋黄橙黄,蛋白透明,整体色泽亮',cause:'蛋黄富含类胡萝卜素',grade:'优',crowd:[{name:'成人',level:'推荐'},{name:'儿童',level:'推荐'},{name:'高血脂人群',level:'慎食'}],note:'高血脂人群每日不超过1个'},
taste:{main:'鲜味',sub:'淡味',intensity:'中',desc:'蛋黄浓郁,蛋白清淡,整体鲜香',crowd:[{name:'成人',level:'推荐'},{name:'儿童',level:'推荐'}],note:'优质蛋白,味道适中'},
texture:{main:'嫩滑',chew:'易',digest:'易',desc:'水煮蛋弹嫩,炒蛋软嫩,蒸蛋细腻',crowd:[{name:'全人群',level:'推荐'},{name:'婴幼儿',level:'推荐'},{name:'老年人',level:'推荐'}],cook:'蒸蛋口感最软,适合各年龄段'}},
{name:'豆腐(北)',code:'0601001',alias:'北豆腐',firstClass:'豆及豆制品',secondClass:'豆制品',icon:'🧈',edible:'100',waterRate:'82.8',dataSource:1,vegTypes:['豆腐块'],
{name:'豆腐(北)',code:'0601001',alias:'北豆腐',firstClass:'豆及豆制品',secondClass:'豆制品',icon:'🧈',edible:'100',waterRate:'82.8',dataSource:1,vegTypes:[{name:'豆腐块',yieldRate:'98'}],
nutri:{calorie:98,protein:12.2,fat:4.8,carbohydrate:1.5,dietary_fiber:0.4,
vitamin_a:0,vitamin_b1:0.07,vitamin_b2:0.04,vitamin_b6:0.05,vitamin_b12:0,vitamin_c:0,vitamin_d:0,vitamin_e:2.71,vitamin_k:0,niacin:0.1,folic_acid:37,biotin:0,pantothenic_acid:0.1,total_choline:0,
ca:138,phosphorus:97,kalium:106,mg:63,na:7.2,fe:2.5,zn:1.11,se:2.3,cu:0.27,mn:0.47,iodine:0,
@@ -397,8 +403,14 @@ function renderBasicInfo(f){
html += `<div class="profile-field"><div class="profile-field__label">可食部分</div><div class="profile-field__value">${f.edible}%</div></div>`;
html += `<div class="profile-field"><div class="profile-field__label">水分</div><div class="profile-field__value">${f.waterRate}%</div></div>`;
html += `<div class="profile-field"><div class="profile-field__label">数据来源</div><div class="profile-field__value">${sourceLabel}</div></div>`;
const vegTypesHtml = f.vegTypes && f.vegTypes.length > 0 ? f.vegTypes.map(t=>`<span class="tag tag-blue">${t}</span>`).join(' ') : '—';
html += `<div class="profile-field"><div class="profile-field__label">净菜类型</div><div class="profile-field__value">${vegTypesHtml}</div></div>`;
let vegTypesValue;
if(f.vegTypes && f.vegTypes.length > 0){
let rows = f.vegTypes.map(t=>`<tr><td>${t.name||'—'}</td><td>${t.yieldRate!==undefined&&t.yieldRate!==''?t.yieldRate+'%':'—'}</td></tr>`).join('');
vegTypesValue = `<table class="veg-type-table"><thead><tr><th>净菜名称</th><th>菜品出净率</th></tr></thead><tbody>${rows}</tbody></table>`;
} else {
vegTypesValue = '—';
}
html += `<div class="profile-field profile-field--full"><div class="profile-field__label">净菜类型</div><div class="profile-field__value">${vegTypesValue}</div></div>`;
html += `</div></div>`;
// 适配人群(汇总色泽/味道/口感档案)
let allCrowd = [];
+186 -181
View File
@@ -1,228 +1,233 @@
# 营养用餐管理端 CHANGELOG
# 钀ュ吇鐢ㄩ绠$悊绔?CHANGELOG
## [2026-06-15] feat: 卫生供应仓储入库页面新增存储方式与区域联动
## [2026-06-17] feat: 净菜包装页新增弹窗与食材表联动调整
- **`sup-pkg-label.html`**
- 净菜包 Tab 的新增弹窗移除“溯源码”,将“净菜名称”拆为“食材名称 + 净菜类型”联动下拉。
- 净菜包弹窗中的“包装规格”改为纯整数数字输入。
- 净菜包列表中的净菜名称示例数据统一调整为 `土豆-土豆丝`
- 餐品净菜包 Tab 的新增/编辑弹窗在食材列表中新增“净菜类型”列,并支持随食材名称联动切换。
## [2026-06-17] feat: 净菜入库弹窗改为食材与净菜类型联动下拉
- **`sup-warehouse.html`**
- 在库库存列表新增「存储方式」列,支持毛菜柜 / 净菜柜 / 仓库三类展示。
- 柜类数据的「所在区域」按明细格式展示为「柜号-格口」,仓库类保持仓区格式。
- 搜索区新增「存储方式」筛选,「所在区域」根据存储方式联动到柜子/仓区级别。
- 库存详情抽屉同步增加「存储方式」字段,修正字段取值索引。
- **`sup-in-raw.html`**
- 毛菜入库列表新增「存储方式」列,支持毛菜柜 / 仓库两种类型。
- 柜类存放区域按「柜号-格口」格式展示,仓库类保持仓区格式。
- 搜索区新增「存储方式」「所在区域」筛选,区域下拉按存储方式联动到柜子/仓区级别。
- 手动入库弹窗新增「存储方式」字段,柜类场景下所在区域下钻到格口级别,仓库场景下选择仓区。
- **`sup-in-cleanin.html`**
- 净菜入库列表新增「存储方式」列,支持净菜柜 / 仓库两种类型
- 柜类存放区域按「柜号-格口」格式展示,仓库类保持仓区格式
- 搜索区新增「存储方式」「所在区域」筛选,区域下拉按存储方式联动到柜子/仓区级别
- 新增净菜入库弹窗新增「存储方式」字段,柜类场景下所在区域下钻到格口级别,仓库场景下选择仓区
- 新增净菜入库弹窗移除“溯源码”字段
- “食材名称”改为下拉框,“净菜类型”改为联动下拉框
- 先选食材后带出对应净菜类型选项,支持如“土豆 -> 土豆丝 / 土豆块 / 土豆泥”
- 兼容从净菜加工页跳转进入时的 `food` / `cleanType` 参数回填
## [2026-06-10] feat: 溯源总览菜单重构——食材溯源 / 餐品溯源 双菜单分离
## [2026-06-17] feat: 鍑€鑿滃唴渚?澶栧敭鏂板寮圭獥鑱斿姩閲嶆瀯
- **侧边栏菜单**:原"溯源查询 / 链路可视化"重构为"食材溯源 / 餐品溯源"两个一级菜单。
- **trace-query.html**(食材溯源主页,沿用原溯源查询):
- 侧边栏菜单文案调整、操作列文案与链接更新(指向 `trace-timeline-ingredient.html`)。
- 表头新增「入库单号」列(位于来源类型与入库时间之间),8 条样例数据补充入库单号字段。
- **trace-dish.html**(新增 · 餐品溯源主页):
- 搜索区:餐品名称(datalist 可搜索下拉)+ 烹制时间(日期区间)。
- 表头:餐品名称 / 烹制单号 / 烹制时间 / 烹制份数 / 烹制厨师 / 食材数量 / 检测结论 / 操作。
- 8 条样例数据,7 绿 1 红(鱼香肉丝不合格)展示双状态样式。
- **trace-timeline-ingredient.html**(新增 · 食材链路详情):
- 内容拆自原 `trace-timeline.html` 的食材维度 tab,去掉维度切换 Tab 与上方搜索区。
- 顶部增加面包屑(食材溯源 / 食材链路),可返回主页。
- **trace-timeline-dish.html**(新增 · 餐品链路详情):
- 内容拆自原 `trace-timeline.html` 的餐品维度 tab,去掉维度切换 Tab 与上方搜索区。
- 保留食材标签页 + 横向管道时间线 + 节点详情 + 视频弹窗 + 面包屑。
- **trace-timeline.html**:删除(被上述两个新链路详情页替代)。
- **prod-proc-cabinet.html**:净菜柜表格中 6 条「溯源」链接由 `trace-timeline.html` 改为 `trace-timeline-ingredient.html`,避免死链;同时修正一处 typo`ttrace-timeline-ingredient.html``trace-timeline-ingredient.html`)。
- **index.html**SITE_MAP 营养管理模块条目同步更新,新增 4 条(食材溯源 / 食材链路 / 餐品溯源 / 餐品链路),移除旧"溯源查询 / 链路可视化"。
- **`sup-clean-internal.html`**锛? - 鏂板缓鐢抽鍗曞脊绐楁敼涓轰笌鍑€鑿滆鍗曚竴鑷寸殑鑱斿姩閫昏緫锛屽噣鑿滃寘妯″紡鎷嗗垎涓恒€岄鏉愩€嶄笌銆屽噣鑿滅被鍨嬨€嶃€? - 鍑€鑿滃寘妯″紡涓嬪寘瑁呰鏍兼敼涓虹函鏁存暟杈撳叆锛岀敵棰嗕唤鏁拌仈鍔ㄨ绠楃敵棰嗘暟閲忋€? - 椁愬搧鍑€鑿滃寘妯″紡涓嬮鍝佸悕绉拌仈鍔ㄥ寘瑁呰鏍间笅鎷夛紝鐢抽鏁伴噺鑷姩璁$畻銆? - 鍒楄〃绀轰緥鏁版嵁鍚屾鏀逛负缁勫悎寮忓睍绀猴紝濡傚湡璞?鍦熻眴涓濄€?- **`sup-clean-external.html`**锛? - 鏂板缓澶栧敭璁㈠崟寮圭獥鏀逛负涓庡噣鑿滆鍗曚竴鑷寸殑鑱斿姩閫昏緫锛屽噣鑿滃寘妯″紡鎷嗗垎涓恒€岄鏉愩€嶄笌銆屽噣鑿滅被鍨嬨€嶃€? - 鍑€鑿滃寘妯″紡涓嬪寘瑁呰鏍兼敼涓虹函鏁存暟杈撳叆锛屽敭鍗栦唤鏁拌仈鍔ㄨ绠楄閲忋€? - 椁愬搧鍑€鑿滃寘妯″紡涓嬮鍝佸悕绉拌仈鍔ㄥ寘瑁呰鏍间笅鎷夛紝璁¢噺鑷姩璁$畻锛屽苟淇濈暀鍗曚环鑱斿姩灏忚銆? - 鍒楄〃绀轰緥鏁版嵁鍚屾鏀逛负缁勫悎寮忓睍绀猴紝濡傚湡璞?鍦熻眴涓濄€?
## [2026-06-17] feat: 鍑€鑿滆鍗曟柊寤哄脊绐楄仈鍔ㄩ噸鏋?
- **`prod-clean-order.html`**锛? - 鏂板缓鍑€鑿滆鍗曞脊绐椾腑锛屽噣鑿滃寘妯″紡鎷嗗垎涓恒€岄鏉愩€嶅拰銆屽噣鑿滅被鍨嬨€嶄袱鍒楋紝骞跺鍔犺仈鍔ㄤ笅鎷夐€夋嫨銆? - 閫夋嫨椋熸潗鍚庤嚜鍔ㄥ甫鍑哄搴斿噣鑿滅被鍨嬪€欓€夐」锛屼緥濡傚湡璞嗚仈鍔ㄥ湡璞嗕笣 / 鍦熻眴鍧?/ 鍦熻眴娉ャ€? - 鍑€鑿滃寘妯″紡涓嬬殑鍖呰瑙勬牸鏀逛负绾暣鏁拌緭鍏ワ紝闇€姹備唤鏁拌仈鍔ㄥ悗鑷姩璁$畻闇€姹傝閲忋€? - 椁愬搧鍑€鑿滃寘妯″紡涓嬶紝椁愬搧鍚嶇О鑱斿姩鍖呰瑙勬牸涓嬫媺锛岄渶姹備唤鏁拌仈鍔ㄥ悗鑷姩璁$畻闇€姹傝閲忋€? - 鍒楄〃涓殑鍑€鑿?椁愬搧绀轰緥鏁版嵁鍚屾鏀逛负缁勫悎灞曠ず锛屽鍦熻眴-鍦熻眴涓濄€?
## [2026-06-17] feat: 椁愬搧鏋勬垚鍑€鑿滅被鍨嬭仈鍔ㄨˉ鍏?
- **`din-dish-add.html`**锛? - 椁愬搧鏋勬垚椋熸潗娓呭崟鍒楄〃涓殑銆岄鏉愬垎绫汇€嶆敼涓恒€屽噣鑿滅被鍨嬨€嶃€? - 鏂板椋熸潗寮圭獥琛ュ厖銆屽噣鑿滅被鍨嬨€嶄笅鎷夋锛屽苟涓庨鏉愬悕绉板仛鑱斿姩閫夋嫨銆? - 閫夋嫨椋熸潗鍚庤嚜鍔ㄥ甫鍑哄搴斿噣鑿滅被鍨嬮€夐」锛屽鍦熻眴鑱斿姩鍦熻眴涓?/ 鍦熻眴鍧?/ 鍦熻眴娉ャ€? - 缂栬緫鎬佷笌杞寲鎬佺殑椁愬搧鏋勬垚鍒楄〃鍥炲~鍚屾鎸夈€屽噣鑿滅被鍨嬨€嶅睍绀恒€? - 鏂板椋熸潗寮圭獥涓殑銆岄鏉愬悕绉般€嶆敼涓烘爣鍑嗕笅鎷夐€夋嫨妗嗭紝淇濇寔涓庛€屽噣鑿滅被鍨嬨€嶈仈鍔ㄣ€?- **`din-dish-all.html`**锛? - 椁愬搧鏋勬垚璇︽儏涓殑椋熸潗鏋勬垚鍒楄〃灏嗐€岄鏉愬垎绫汇€嶆敼涓恒€屽噣鑿滅被鍨嬨€嶃€? - 璇︽儏椤靛唴鏂板椋熸潗寮圭獥鍗犱綅瀛楁鍚屾鏀逛负銆屽噣鑿滅被鍨嬨€嶏紝淇濇寔椤甸潰璇箟涓€鑷淬€?
## [2026-06-15] feat: 鍗敓渚涘簲浠撳偍鍏ュ簱椤甸潰鏂板瀛樺偍鏂瑰紡涓庡尯鍩熻仈鍔?
- **`sup-warehouse.html`**锛? - 鍦ㄥ簱搴撳瓨鍒楄〃鏂板銆屽瓨鍌ㄦ柟寮忋€嶅垪锛屾敮鎸佹瘺鑿滄煖 / 鍑€鑿滄煖 / 浠撳簱涓夌被灞曠ず銆? - 鏌滅被鏁版嵁鐨勩€屾墍鍦ㄥ尯鍩熴€嶆寜鏄庣粏鏍煎紡灞曠ず涓恒€屾煖鍙?鏍煎彛銆嶏紝浠撳簱绫讳繚鎸佷粨鍖烘牸寮忋€? - 鎼滅储鍖烘柊澧炪€屽瓨鍌ㄦ柟寮忋€嶇瓫閫夛紝銆屾墍鍦ㄥ尯鍩熴€嶆牴鎹瓨鍌ㄦ柟寮忚仈鍔ㄥ埌鏌滃瓙/浠撳尯绾у埆銆? - 搴撳瓨璇︽儏鎶藉眽鍚屾澧炲姞銆屽瓨鍌ㄦ柟寮忋€嶅瓧娈碉紝淇瀛楁鍙栧€肩储寮曘€?- **`sup-in-raw.html`**锛? - 姣涜彍鍏ュ簱鍒楄〃鏂板銆屽瓨鍌ㄦ柟寮忋€嶅垪锛屾敮鎸佹瘺鑿滄煖 / 浠撳簱涓ょ绫诲瀷銆? - 鏌滅被瀛樻斁鍖哄煙鎸夈€屾煖鍙?鏍煎彛銆嶆牸寮忓睍绀猴紝浠撳簱绫讳繚鎸佷粨鍖烘牸寮忋€? - 鎼滅储鍖烘柊澧炪€屽瓨鍌ㄦ柟寮忋€嶃€屾墍鍦ㄥ尯鍩熴€嶇瓫閫夛紝鍖哄煙涓嬫媺鎸夊瓨鍌ㄦ柟寮忚仈鍔ㄥ埌鏌滃瓙/浠撳尯绾у埆銆? - 鎵嬪姩鍏ュ簱寮圭獥鏂板銆屽瓨鍌ㄦ柟寮忋€嶅瓧娈碉紝鏌滅被鍦烘櫙涓嬫墍鍦ㄥ尯鍩熶笅閽诲埌鏍煎彛绾у埆锛屼粨搴撳満鏅笅閫夋嫨浠撳尯銆?- **`sup-in-cleanin.html`**锛? - 鍑€鑿滃叆搴撳垪琛ㄦ柊澧炪€屽瓨鍌ㄦ柟寮忋€嶅垪锛屾敮鎸佸噣鑿滄煖 / 浠撳簱涓ょ绫诲瀷銆? - 鏌滅被瀛樻斁鍖哄煙鎸夈€屾煖鍙?鏍煎彛銆嶆牸寮忓睍绀猴紝浠撳簱绫讳繚鎸佷粨鍖烘牸寮忋€? - 鎼滅储鍖烘柊澧炪€屽瓨鍌ㄦ柟寮忋€嶃€屾墍鍦ㄥ尯鍩熴€嶇瓫閫夛紝鍖哄煙涓嬫媺鎸夊瓨鍌ㄦ柟寮忚仈鍔ㄥ埌鏌滃瓙/浠撳尯绾у埆銆? - 鏂板鍑€鑿滃叆搴撳脊绐楁柊澧炪€屽瓨鍌ㄦ柟寮忋€嶅瓧娈碉紝鏌滅被鍦烘櫙涓嬫墍鍦ㄥ尯鍩熶笅閽诲埌鏍煎彛绾у埆锛屼粨搴撳満鏅笅閫夋嫨浠撳尯銆?
## [2026-06-10] feat: 婧簮鎬昏鑿滃崟閲嶆瀯鈥斺€旈鏉愭函婧?/ 椁愬搧婧簮 鍙岃彍鍗曞垎绂?
- **渚ц竟鏍忚彍鍗?*锛氬師"婧簮鏌ヨ / 閾捐矾鍙鍖?閲嶆瀯涓?椋熸潗婧簮 / 椁愬搧婧簮"涓や釜涓€绾ц彍鍗曘€?- **trace-query.html**锛堥鏉愭函婧愪富椤碉紝娌跨敤鍘熸函婧愭煡璇級锛?
- 渚ц竟鏍忚彍鍗曟枃妗堣皟鏁淬€佹搷浣滃垪鏂囨涓庨摼鎺ユ洿鏂帮紙鎸囧悜 `trace-timeline-ingredient.html`锛夈€?
- 琛ㄥご鏂板銆屽叆搴撳崟鍙枫€嶅垪锛堜綅浜庢潵婧愮被鍨嬩笌鍏ュ簱鏃堕棿涔嬮棿锛夛紝8 鏉℃牱渚嬫暟鎹ˉ鍏呭叆搴撳崟鍙峰瓧娈点€?
- **trace-dish.html**锛堟柊澧?路 椁愬搧婧簮涓婚〉锛夛細
- 鎼滅储鍖猴細椁愬搧鍚嶇О锛坉atalist 鍙悳绱笅鎷夛級+ 鐑瑰埗鏃堕棿锛堟棩鏈熷尯闂达級銆?
- 琛ㄥご锛氶鍝佸悕绉?/ 鐑瑰埗鍗曞彿 / 鐑瑰埗鏃堕棿 / 鐑瑰埗浠芥暟 / 鐑瑰埗鍘ㄥ笀 / 椋熸潗鏁伴噺 / 妫€娴嬬粨璁?/ 鎿嶄綔銆?
- 8 鏉℃牱渚嬫暟鎹紝7 缁?1 绾紙楸奸鑲変笣涓嶅悎鏍硷級灞曠ず鍙岀姸鎬佹牱寮忋€?
- **trace-timeline-ingredient.html**锛堟柊澧?路 椋熸潗閾捐矾璇︽儏锛夛細
- 鍐呭鎷嗚嚜鍘?`trace-timeline.html` 鐨勯鏉愮淮搴?tab锛屽幓鎺夌淮搴﹀垏鎹?Tab 涓庝笂鏂规悳绱㈠尯銆?
- 椤堕儴澧炲姞闈㈠寘灞戯紙椋熸潗婧簮 / 椋熸潗閾捐矾锛夛紝鍙繑鍥炰富椤点€?
- **trace-timeline-dish.html**锛堟柊澧?路 椁愬搧閾捐矾璇︽儏锛夛細
- 鍐呭鎷嗚嚜鍘?`trace-timeline.html` 鐨勯鍝佺淮搴?tab锛屽幓鎺夌淮搴﹀垏鎹?Tab 涓庝笂鏂规悳绱㈠尯銆?
- 淇濈暀椋熸潗鏍囩椤?+ 妯悜绠¢亾鏃堕棿绾?+ 鑺傜偣璇︽儏 + 瑙嗛寮圭獥 + 闈㈠寘灞戙€?
- **trace-timeline.html**锛氬垹闄わ紙琚笂杩颁袱涓柊閾捐矾璇︽儏椤垫浛浠o級銆?
- **prod-proc-cabinet.html**锛氬噣鑿滄煖琛ㄦ牸涓?6 鏉°€屾函婧愩€嶉摼鎺ョ敱 `trace-timeline.html` 鏀逛负 `trace-timeline-ingredient.html`锛岄伩鍏嶆閾撅紱鍚屾椂淇涓€澶?typo锛坄ttrace-timeline-ingredient.html` 鈫?`trace-timeline-ingredient.html`锛夈€?
- **index.html**锛歋ITE_MAP 钀ュ吇绠$悊妯″潡鏉$洰鍚屾鏇存柊锛屾柊澧?4 鏉★紙椋熸潗婧簮 / 椋熸潗閾捐矾 / 椁愬搧婧簮 / 椁愬搧閾捐矾锛夛紝绉婚櫎鏃?婧簮鏌ヨ / 閾捐矾鍙鍖?銆?
## [2026-06-08] feat: 溯源模块重构——餐品/食材双维度分离
## [2026-06-08] feat: 婧簮妯″潡閲嶆瀯鈥斺€旈鍝?椋熸潗鍙岀淮搴﹀垎绂?
- **trace-query.html**:表格表头、筛选条件、数据行从餐品维度切换为食材维度(溯源码、食材名称、来源类型、入库时间、产地/供应商、种养殖批次、检测结论、操作)
- **trace-timeline.html**
- 搜索区重构:删除共享搜索栏,餐品维度和食材维度各自独立 filter-bar
- 餐品维度:搜索条件为餐品名称(下拉)+ 烹制时间(日期区间,默认当天);概要信息展示餐品名称、烹制单号、烹制时间、烹制厨师、食材数量
- 食材维度:搜索条件为食材名称(下拉)+ 溯源码 + 入库时间(日期区间,默认当天);概要信息展示食材名称、溯源码、入库单号、来源类型、供应商、入库量
- **trace-query.html**锛氳〃鏍艰〃澶淬€佺瓫閫夋潯浠躲€佹暟鎹浠庨鍝佺淮搴﹀垏鎹负椋熸潗缁村害锛堟函婧愮爜銆侀鏉愬悕绉般€佹潵婧愮被鍨嬨€佸叆搴撴椂闂淬€佷骇鍦?渚涘簲鍟嗐€佺鍏绘畺鎵规銆佹娴嬬粨璁恒€佹搷浣滐級
- **trace-timeline.html**锛?
- 鎼滅储鍖洪噸鏋勶細鍒犻櫎鍏变韩鎼滅储鏍忥紝椁愬搧缁村害鍜岄鏉愮淮搴﹀悇鑷嫭绔?filter-bar
- 椁愬搧缁村害锛氭悳绱㈡潯浠朵负椁愬搧鍚嶇О锛堜笅鎷夛級+ 鐑瑰埗鏃堕棿锛堟棩鏈熷尯闂达紝榛樿褰撳ぉ锛夛紱姒傝淇℃伅灞曠ず椁愬搧鍚嶇О銆佺児鍒跺崟鍙枫€佺児鍒舵椂闂淬€佺児鍒跺帹甯堛€侀鏉愭暟閲?
- 椋熸潗缁村害锛氭悳绱㈡潯浠朵负椋熸潗鍚嶇О锛堜笅鎷夛級+ 婧簮鐮?+ 鍏ュ簱鏃堕棿锛堟棩鏈熷尯闂达紝榛樿褰撳ぉ锛夛紱姒傝淇℃伅灞曠ず椋熸潗鍚嶇О銆佹函婧愮爜銆佸叆搴撳崟鍙枫€佹潵婧愮被鍨嬨€佷緵搴斿晢銆佸叆搴撻噺
## [2026-05-26]
### 优化 — 营养模块全量术语更新(食堂/餐厅→场所)
### 浼樺寲 鈥?钀ュ吇妯″潡鍏ㄩ噺鏈鏇存柊锛堥鍫?椁愬巺鈫掑満鎵€锛?
**全模块 63 HTML 页面完整术语替换**
**鍏ㄦā鍧?63 涓?HTML 椤甸潰瀹屾暣鏈鏇挎崲**锛?
- **菜单导航**:所有页面侧边栏菜单"食堂管理" → "场所管理"
- **页面标题与表格标题**:所有涉及"食堂"/"餐厅"的页面标题、表格列标题统一改为"场所"
- **表单字段标签**
- "食堂名称" → "场所名称"
- "食堂编号" → "场所编号"
- "当前食堂" → "当前场所"
- "选择食堂" → "选择场所"
- "申领食堂" → "申领场所"
- "当前餐厅" → "当前场所"
- **筛选栏与下拉选项**:所有筛选项、下拉菜单中的"食堂"改为"场所"
- **表格数据行**:表格中的"食堂"术语改为"场所"(如"一号食堂厨房" → "一号场所厨房"
- **JavaScript 代码**:Drawer 详情项、表单字段标签等代码中的"食堂"改为"场所"
- **注释**:代码注释中的"食堂切换" → "场所切换"
- **鑿滃崟瀵艰埅**锛氭墍鏈夐〉闈晶杈规爮鑿滃崟"椋熷爞绠$悊" 鈫?"鍦烘墍绠$悊"
- **椤甸潰鏍囬涓庤〃鏍兼爣棰?*锛氭墍鏈夋秹鍙?椋熷爞"/"椁愬巺"鐨勯〉闈㈡爣棰樸€佽〃鏍煎垪鏍囬缁熶竴鏀逛负"鍦烘墍"
- **琛ㄥ崟瀛楁鏍囩**锛?
- "椋熷爞鍚嶇О" 鈫?"鍦烘墍鍚嶇О"
- "椋熷爞缂栧彿" 鈫?"鍦烘墍缂栧彿"
- "褰撳墠椋熷爞" 鈫?"褰撳墠鍦烘墍"
- "閫夋嫨椋熷爞" 鈫?"閫夋嫨鍦烘墍"
- "鐢抽椋熷爞" 鈫?"鐢抽鍦烘墍"
- "褰撳墠椁愬巺" 鈫?"褰撳墠鍦烘墍"
- **绛涢€夋爮涓庝笅鎷夐€夐」**锛氭墍鏈夌瓫閫夐」銆佷笅鎷夎彍鍗曚腑鐨?椋熷爞"鏀逛负"鍦烘墍"
- **琛ㄦ牸鏁版嵁琛?*锛氳〃鏍间腑鐨?椋熷爞"鏈鏀逛负"鍦烘墍"锛堝"涓€鍙烽鍫傚帹鎴? 鈫?"涓€鍙峰満鎵€鍘ㄦ埧"锛?
- **JavaScript 浠g爜**锛欴rawer 璇︽儏椤广€佽〃鍗曞瓧娈垫爣绛剧瓑浠g爜涓殑"椋熷爞"鏀逛负"鍦烘墍"
- **娉ㄩ噴**锛氫唬鐮佹敞閲婁腑鐨?椋熷爞鍒囨崲" 鈫?"鍦烘墍鍒囨崲"
**保留规则**
- 具体场所名称(如"总部一号食堂"、"采气一厂营养餐厅"等)保留不改
- 类型选项(单选框中的"食堂"/"餐厅")保留不改
- 数据库字段名保留不改
**淇濈暀瑙勫垯**锛?
- 鍏蜂綋鍦烘墍鍚嶇О锛堝"鎬婚儴涓€鍙烽鍫?銆?閲囨皵涓€鍘傝惀鍏婚鍘?绛夛級淇濈暀涓嶆敼
- 绫诲瀷閫夐」锛堝崟閫夋涓殑"椋熷爞"/"椁愬巺"锛変繚鐣欎笉鏀?
- 鏁版嵁搴撳瓧娈靛悕淇濈暀涓嶆敼
**涉及文件**(共 20+ 个):
- 场所管理:`din-canteen.html`, `din-canteen-add.html`, `din-canteen-line.html`
- 用餐管理:`din-user-mgmt.html`, `din-order-meal.html`, `din-order-pickup.html`, `din-order-line.html`
- 生产管理:`prod-clean-order.html`, `prod-proc-cabinet.html`, `prod-proc-combo.html`, `prod-proc-cook.html`, `prod-proc-serve.html`, `prod-proc-stats.html`, `prod-proc-surplus.html`, `prod-qc-daily.html`, `prod-qc-nutrition.html`, `prod-qc-nutrition-add.html`
- 供应管理:`sup-clean-internal.html`, `sup-clean-external.html`, `sup-in-cleanin.html`
- 其他:`din-data-benefit.html`, `din-data-nutri.html`, `din-innovation.html`, `din-recipe-mgmt.html`, `din-terminal.html`, `farm-purchase.html`
**娑夊強鏂囦欢**锛堝叡 20+ 涓級锛?
- 鍦烘墍绠$悊锛歚din-canteen.html`, `din-canteen-add.html`, `din-canteen-line.html`
- 鐢ㄩ绠$悊锛歚din-user-mgmt.html`, `din-order-meal.html`, `din-order-pickup.html`, `din-order-line.html`
- 鐢熶骇绠$悊锛歚prod-clean-order.html`, `prod-proc-cabinet.html`, `prod-proc-combo.html`, `prod-proc-cook.html`, `prod-proc-serve.html`, `prod-proc-stats.html`, `prod-proc-surplus.html`, `prod-qc-daily.html`, `prod-qc-nutrition.html`, `prod-qc-nutrition-add.html`
- 渚涘簲绠$悊锛歚sup-clean-internal.html`, `sup-clean-external.html`, `sup-in-cleanin.html`
- 鍏朵粬锛歚din-data-benefit.html`, `din-data-nutri.html`, `din-innovation.html`, `din-recipe-mgmt.html`, `din-terminal.html`, `farm-purchase.html`
### 优化 — 场所管理模块命名与功能完善
### 浼樺寲 鈥?鍦烘墍绠$悊妯″潡鍛藉悕涓庡姛鑳藉畬鍠?
- **`din-canteen.html`** 场所管理(原食堂管理)
- 菜单名称:食堂管理 → 场所管理
- 页面标题、表格标题、按钮文案中的"食堂"统一改为"场所"
- 筛选栏字段:食堂名称 → 场所名称,食堂编号 → 场所编号
- 表格列顺序调整:场所编号、场所名称、**场所类型**、所属单位、详细地址、操作
- 新增"场所类型"列,显示"食堂"或"餐厅"标签(蓝色/绿色区分)
- 详情抽屉标题:食堂详情 → 场所详情
- 详情抽屉字段顺序调整:场所编号、场所名称、场所类型、所属单位、详细地址、负责人、负责人电话、使用三减终端
- **`din-canteen.html`** 鍦烘墍绠$悊锛堝師椋熷爞绠$悊锛?
- 鑿滃崟鍚嶇О锛氶鍫傜鐞?鈫?鍦烘墍绠$悊
- 椤甸潰鏍囬銆佽〃鏍兼爣棰樸€佹寜閽枃妗堜腑鐨?椋熷爞"缁熶竴鏀逛负"鍦烘墍"
- 绛涢€夋爮瀛楁锛氶鍫傚悕绉?鈫?鍦烘墍鍚嶇О锛岄鍫傜紪鍙?鈫?鍦烘墍缂栧彿
- 琛ㄦ牸鍒楅『搴忚皟鏁达細鍦烘墍缂栧彿銆佸満鎵€鍚嶇О銆?*鍦烘墍绫诲瀷**銆佹墍灞炲崟浣嶃€佽缁嗗湴鍧€銆佹搷浣?
- 鏂板"鍦烘墍绫诲瀷"鍒楋紝鏄剧ず"椋熷爞"鎴?椁愬巺"鏍囩锛堣摑鑹?缁胯壊鍖哄垎锛?
- 璇︽儏鎶藉眽鏍囬锛氶鍫傝鎯?鈫?鍦烘墍璇︽儏
- 璇︽儏鎶藉眽瀛楁椤哄簭璋冩暣锛氬満鎵€缂栧彿銆佸満鎵€鍚嶇О銆佸満鎵€绫诲瀷銆佹墍灞炲崟浣嶃€佽缁嗗湴鍧€銆佽礋璐d汉銆佽礋璐d汉鐢佃瘽銆佷娇鐢ㄤ笁鍑忕粓绔?
- **`din-canteen-add.html`** 新增/编辑场所
- 页面标题:新增食堂 → 新增场所
- 面包屑导航:食堂管理 → 场所管理,新增食堂 → 新增场所
- 表单字段:食堂名称 → 场所名称,食堂编号 → 场所编号,食堂所属单位 → 场所所属单位
- 新增"场所类型"单选框字段(食堂/餐厅),位置在场所编号之后
- 保存提示文案:返回食堂列表页 → 返回场所列表页
- **`din-canteen-add.html`** 鏂板/缂栬緫鍦烘墍
- 椤甸潰鏍囬锛氭柊澧為鍫?鈫?鏂板鍦烘墍
- 闈㈠寘灞戝鑸細椋熷爞绠$悊 鈫?鍦烘墍绠$悊锛屾柊澧為鍫?鈫?鏂板鍦烘墍
- 琛ㄥ崟瀛楁锛氶鍫傚悕绉?鈫?鍦烘墍鍚嶇О锛岄鍫傜紪鍙?鈫?鍦烘墍缂栧彿锛岄鍫傛墍灞炲崟浣?鈫?鍦烘墍鎵€灞炲崟浣?
- 鏂板"鍦烘墍绫诲瀷"鍗曢€夋瀛楁锛堥鍫?椁愬巺锛夛紝浣嶇疆鍦ㄥ満鎵€缂栧彿涔嬪悗
- 淇濆瓨鎻愮ず鏂囨锛氳繑鍥為鍫傚垪琛ㄩ〉 鈫?杩斿洖鍦烘墍鍒楄〃椤?
- **`din-canteen-line.html`** 餐线管理
- 侧边栏菜单:食堂管理 → 场所管理
- **`din-canteen-line.html`** 椁愮嚎绠$悊
- 渚ц竟鏍忚彍鍗曪細椋熷爞绠$悊 鈫?鍦烘墍绠$悊
## [2026-05-25]
### 修复 — 绿色种采 · 土地环境页面结构修正
### 淇 鈥?缁胯壊绉嶉噰 路 鍦熷湴鐜椤甸潰缁撴瀯淇
- **`farm-land.html`** 土地环境
- 种植环境表格列顺序调整:「土壤类型/负责人/地块状态」前置,「种植作物/灌溉方式」后移,与详情 Drawer 取值逻辑保持一致
- 养殖环境表格列顺序调整:「负责人/养殖状态」前置,「动物种类/养殖方式」后移
- 筛选栏「种植作物」由固定 select 改为自由文本输入框,「动物种类」同步调整
- 新增地块弹窗精简字段:移除「种植作物(搜索选择框)」「地块状态」「灌溉方式」三项(由后续流程维护)
- 新增养殖区弹窗精简字段:移除「动物种类」「养殖方式」「养殖状态」三项
- 移除种植作物搜索选择框(search-select)及其 JS 初始化逻辑
- 修正 `showPlotDetail` / `showBreedDetail` 函数中 td 索引,与调整后列顺序保持一致
- 休耕/空置状态行的「种植作物」「灌溉方式」(或「动物种类」「养殖方式」)数据清空,避免显示旧的脏数据
- **`farm-land.html`** 鍦熷湴鐜
- 绉嶆鐜琛ㄦ牸鍒楅『搴忚皟鏁达細銆屽湡澹ょ被鍨?璐熻矗浜?鍦板潡鐘舵€併€嶅墠缃紝銆岀妞嶄綔鐗?鐏屾簤鏂瑰紡銆嶅悗绉伙紝涓庤鎯?Drawer 鍙栧€奸€昏緫淇濇寔涓€鑷?
- 鍏绘畺鐜琛ㄦ牸鍒楅『搴忚皟鏁达細銆岃礋璐d汉/鍏绘畺鐘舵€併€嶅墠缃紝銆屽姩鐗╃绫?鍏绘畺鏂瑰紡銆嶅悗绉?
- 绛涢€夋爮銆岀妞嶄綔鐗┿€嶇敱鍥哄畾 select 鏀逛负鑷敱鏂囨湰杈撳叆妗嗭紝銆屽姩鐗╃绫汇€嶅悓姝ヨ皟鏁?
- 鏂板鍦板潡寮圭獥绮剧畝瀛楁锛氱Щ闄ゃ€岀妞嶄綔鐗╋紙鎼滅储閫夋嫨妗嗭級銆嶃€屽湴鍧楃姸鎬併€嶃€岀亴婧夋柟寮忋€嶄笁椤癸紙鐢卞悗缁祦绋嬬淮鎶わ級
- 鏂板鍏绘畺鍖哄脊绐楃簿绠€瀛楁锛氱Щ闄ゃ€屽姩鐗╃绫汇€嶃€屽吇娈栨柟寮忋€嶃€屽吇娈栫姸鎬併€嶄笁椤?
- 绉婚櫎绉嶆浣滅墿鎼滅储閫夋嫨妗嗭紙search-select锛夊強鍏?JS 鍒濆鍖栭€昏緫
- 淇 `showPlotDetail` / `showBreedDetail` 鍑芥暟涓?td 绱㈠紩锛屼笌璋冩暣鍚庡垪椤哄簭淇濇寔涓€鑷?
- 浼戣€?绌虹疆鐘舵€佽鐨勩€岀妞嶄綔鐗┿€嶃€岀亴婧夋柟寮忋€嶏紙鎴栥€屽姩鐗╃绫汇€嶃€屽吇娈栨柟寮忋€嶏級鏁版嵁娓呯┖锛岄伩鍏嶆樉绀烘棫鐨勮剰鏁版嵁
## [2026-05-22]
### 增强 — 营养用餐模块多页面交互优化
### 澧炲己 鈥?钀ュ吇鐢ㄩ妯″潡澶氶〉闈氦浜掍紭鍖?
- **`din-data-nutri.html`** 营养管理数据
- 新增页面信息栏(标题 + 食堂切换下拉,canteen-select 高亮样式)
- 新增周选择器(week-picker):覆盖原生日期文字,显示友好的周范围标签
- 餐品明细弹窗重构:宽度调整为 900px,移除顶部提示条,底部汇总区移至表格下方,新增 `.dish-tip` 警告样式(橙色背景)
- 新增二级弹窗表单样式(wb-form-modal / wb-form-row / wb-form-input 等),支持营养师工作台内嵌表单
- 新增 `.modal-overlay.layer` 层叠弹窗样式(z-index:1010
- 新增 `.tag-purple` 标签色
- **`din-data-nutri.html`** 钀ュ吇绠$悊鏁版嵁
- 鏂板椤甸潰淇℃伅鏍忥紙鏍囬 + 椋熷爞鍒囨崲涓嬫媺锛宑anteen-select 楂樹寒鏍峰紡锛?
- 鏂板鍛ㄩ€夋嫨鍣紙week-picker锛夛細瑕嗙洊鍘熺敓鏃ユ湡鏂囧瓧锛屾樉绀哄弸濂界殑鍛ㄨ寖鍥存爣绛?
- 椁愬搧鏄庣粏寮圭獥閲嶆瀯锛氬搴﹁皟鏁翠负 900px锛岀Щ闄ら《閮ㄦ彁绀烘潯锛屽簳閮ㄦ眹鎬诲尯绉昏嚦琛ㄦ牸涓嬫柟锛屾柊澧?`.dish-tip` 璀﹀憡鏍峰紡锛堟鑹茶儗鏅級
- 鏂板浜岀骇寮圭獥琛ㄥ崟鏍峰紡锛坵b-form-modal / wb-form-row / wb-form-input 绛夛級锛屾敮鎸佽惀鍏诲笀宸ヤ綔鍙板唴宓岃〃鍗?
- 鏂板 `.modal-overlay.layer` 灞傚彔寮圭獥鏍峰紡锛坺-index:1010锛?
- 鏂板 `.tag-purple` 鏍囩鑹?
- **`din-data-benefit.html`** 食材效益
- 新增页面信息栏(标题 + 食堂切换下拉)
- 食材分类筛选改为二级级联选择器(cascade-picker),支持一级/二级联动选择
- 新增「↻ 重置」按钮(btn-reset 样式)
- 表格移除「损耗原因」列
- 统计周期数据更新为 2026-05
- **`din-data-benefit.html`** 椋熸潗鏁堢泭
- 鏂板椤甸潰淇℃伅鏍忥紙鏍囬 + 椋熷爞鍒囨崲涓嬫媺锛?
- 椋熸潗鍒嗙被绛涢€夋敼涓轰簩绾х骇鑱旈€夋嫨鍣紙cascade-picker锛夛紝鏀寔涓€绾?浜岀骇鑱斿姩閫夋嫨
- 鏂板銆屸喕 閲嶇疆銆嶆寜閽紙btn-reset 鏍峰紡锛?
- 琛ㄦ牸绉婚櫎銆屾崯鑰楀師鍥犮€嶅垪
- 缁熻鍛ㄦ湡鏁版嵁鏇存柊涓?2026-05
- **`din-model-llm.html`** 大模型管理
- 表格新增「API_KEY」「API_URL」列,「提供商」改为「供应商」
- 状态标签由「在用/备用」改为「启用/停用」
- 操作列新增「编辑」链接
- 新增「接入新模型」弹窗(含模型名称/供应商/API_KEY/API_URL/版本/接入方式/使用场景/初始状态字段)
- 新增「编辑模型」弹窗(预填当前行数据,支持修改所有字段)
- 调试日志弹窗适配新列索引(provider 从第3列改为第5列)
- **`din-model-llm.html`** 澶фā鍨嬬鐞?
- 琛ㄦ牸鏂板銆孉PI_KEY銆嶃€孉PI_URL銆嶅垪锛屻€屾彁渚涘晢銆嶆敼涓恒€屼緵搴斿晢銆?
- 鐘舵€佹爣绛剧敱銆屽湪鐢?澶囩敤銆嶆敼涓恒€屽惎鐢?鍋滅敤銆?
- 鎿嶄綔鍒楁柊澧炪€岀紪杈戙€嶉摼鎺?
- 鏂板銆屾帴鍏ユ柊妯″瀷銆嶅脊绐楋紙鍚ā鍨嬪悕绉?渚涘簲鍟?API_KEY/API_URL/鐗堟湰/鎺ュ叆鏂瑰紡/浣跨敤鍦烘櫙/鍒濆鐘舵€佸瓧娈碉級
- 鏂板銆岀紪杈戞ā鍨嬨€嶅脊绐楋紙棰勫~褰撳墠琛屾暟鎹紝鏀寔淇敼鎵€鏈夊瓧娈碉級
- 璋冭瘯鏃ュ織寮圭獥閫傞厤鏂板垪绱㈠紩锛坧rovider 浠庣3鍒楁敼涓虹5鍒楋級
- **`din-model-small.html`** 小模型管理
- 新增「新增模型」弹窗(含模型名称/类型/版本/部署方式/使用场景/初始状态字段)
- 新增弹窗表单通用样式(add-form-row / add-form-item
- **`din-model-small.html`** 灏忔ā鍨嬬鐞?
- 鏂板銆屾柊澧炴ā鍨嬨€嶅脊绐楋紙鍚ā鍨嬪悕绉?绫诲瀷/鐗堟湰/閮ㄧ讲鏂瑰紡/浣跨敤鍦烘櫙/鍒濆鐘舵€佸瓧娈碉級
- 鏂板寮圭獥琛ㄥ崟閫氱敤鏍峰紡锛坅dd-form-row / add-form-item锛?
- **`din-terminal.html`** 终端管理
- 新增页面信息栏(标题 + 食堂切换下拉)
- 筛选栏重构:「设备名称/编号」拆分为两个独立输入框,移除「所在区域」「厂家品牌」「责任人」筛选项
- 表格列精简:移除「SN序列号」「所在区域」「地理位置」列
- 新增设备弹窗表单字段调整:「SN序列号」改为「设备编号」,新增「型号」字段,移除「所在区域」「地理位置」
- **`din-terminal.html`** 缁堢绠$悊
- 鏂板椤甸潰淇℃伅鏍忥紙鏍囬 + 椋熷爞鍒囨崲涓嬫媺锛?
- 绛涢€夋爮閲嶆瀯锛氥€岃澶囧悕绉?缂栧彿銆嶆媶鍒嗕负涓や釜鐙珛杈撳叆妗嗭紝绉婚櫎銆屾墍鍦ㄥ尯鍩熴€嶃€屽巶瀹跺搧鐗屻€嶃€岃矗浠讳汉銆嶇瓫閫夐」
- 琛ㄦ牸鍒楃簿绠€锛氱Щ闄ゃ€孲N搴忓垪鍙枫€嶃€屾墍鍦ㄥ尯鍩熴€嶃€屽湴鐞嗕綅缃€嶅垪
- 鏂板璁惧寮圭獥琛ㄥ崟瀛楁璋冩暣锛氥€孲N搴忓垪鍙枫€嶆敼涓恒€岃澶囩紪鍙枫€嶏紝鏂板銆屽瀷鍙枫€嶅瓧娈碉紝绉婚櫎銆屾墍鍦ㄥ尯鍩熴€嶃€屽湴鐞嗕綅缃€?
- **`din-order-line.html`** 餐线管理
- 三个 Tab(秤台实时/餐线汇总/秤台汇总)操作列统一移除「编辑」链接,仅保留「详情」
- **`din-order-line.html`** 椁愮嚎绠$悊
- 涓変釜 Tab锛堢Г鍙板疄鏃?椁愮嚎姹囨€?绉ゅ彴姹囨€伙級鎿嶄綔鍒楃粺涓€绉婚櫎銆岀紪杈戙€嶉摼鎺ワ紝浠呬繚鐣欍€岃鎯呫€?
## [2026-05-20]
### 增强 — 健康生产模块交互重构与食堂切换
### 澧炲己 鈥?鍋ュ悍鐢熶骇妯″潡浜や簰閲嶆瀯涓庨鍫傚垏鎹?
- **`prod-proc-combo.html`** 净菜组配
- 筛选栏新增「当前食堂」「任务来源」「任务截止日期」筛选,截止日期默认当天
- 表头重构:去掉需求规格列,新增餐品规格/份数/任务截止时间/任务来源/完成时间列
- 食材配方列移至任务截止时间后,「查看配方」改为「食材明细」
- 操作列重构:固定三项(食材溯源链路、查看视频、更多▾ hover 下拉)+ 状态按钮
- 新建组配任务弹窗重构:改用下拉选择餐品/规格/份数/来源,移除手动食材清单
- 食材明细弹窗新增「分类」列(主材/辅材/调料 标签)
- overflow-y 改为 visible 解决下拉菜单遮挡问题
- **`prod-proc-combo.html`** 鍑€鑿滅粍閰?
- 绛涢€夋爮鏂板銆屽綋鍓嶉鍫傘€嶃€屼换鍔℃潵婧愩€嶃€屼换鍔℃埅姝㈡棩鏈熴€嶇瓫閫夛紝鎴鏃ユ湡榛樿褰撳ぉ
- 琛ㄥご閲嶆瀯锛氬幓鎺夐渶姹傝鏍煎垪锛屾柊澧為鍝佽鏍?浠芥暟/浠诲姟鎴鏃堕棿/浠诲姟鏉ユ簮/瀹屾垚鏃堕棿鍒?
- 椋熸潗閰嶆柟鍒楃Щ鑷充换鍔℃埅姝㈡椂闂村悗锛屻€屾煡鐪嬮厤鏂广€嶆敼涓恒€岄鏉愭槑缁嗐€?
- 鎿嶄綔鍒楅噸鏋勶細鍥哄畾涓夐」锛堥鏉愭函婧愰摼璺€佹煡鐪嬭棰戙€佹洿澶氣柧 hover 涓嬫媺锛? 鐘舵€佹寜閽?
- 鏂板缓缁勯厤浠诲姟寮圭獥閲嶆瀯锛氭敼鐢ㄤ笅鎷夐€夋嫨椁愬搧/瑙勬牸/浠芥暟/鏉ユ簮锛岀Щ闄ゆ墜鍔ㄩ鏉愭竻鍗?
- 椋熸潗鏄庣粏寮圭獥鏂板銆屽垎绫汇€嶅垪锛堜富鏉?杈呮潗/璋冩枡 鏍囩锛?
- overflow-y 鏀逛负 visible 瑙e喅涓嬫媺鑿滃崟閬尅闂
- **`prod-proc-cook.html`** 按单烹制
- 筛选栏新增「当前食堂」「烹制日期」筛选,烹制日期默认当天
- 表头重构:去掉计划/实际烹制规格、视频记录,新增餐品规格/需求份数/烹制份数/烹制日期
- 烹制状态前移至烹制份数后,食材明细/温度过程/模型数据列前移至生重/熟重/生熟比前
- 生熟比格式改为 10.8x
- 操作列重构:固定三项 + hover 下拉 + 状态按钮(通知取餐/烹制完成/开始烹制)
- overflow-y 改为 visible
- **`prod-proc-cook.html`** 鎸夊崟鐑瑰埗
- 绛涢€夋爮鏂板銆屽綋鍓嶉鍫傘€嶃€岀児鍒舵棩鏈熴€嶇瓫閫夛紝鐑瑰埗鏃ユ湡榛樿褰撳ぉ
- 琛ㄥご閲嶆瀯锛氬幓鎺夎鍒?瀹為檯鐑瑰埗瑙勬牸銆佽棰戣褰曪紝鏂板椁愬搧瑙勬牸/闇€姹備唤鏁?鐑瑰埗浠芥暟/鐑瑰埗鏃ユ湡
- 鐑瑰埗鐘舵€佸墠绉昏嚦鐑瑰埗浠芥暟鍚庯紝椋熸潗鏄庣粏/娓╁害杩囩▼/妯″瀷鏁版嵁鍒楀墠绉昏嚦鐢熼噸/鐔熼噸/鐢熺啛姣斿墠
- 鐢熺啛姣旀牸寮忔敼涓?1锛?.8x
- 鎿嶄綔鍒楅噸鏋勶細鍥哄畾涓夐」 + hover 涓嬫媺 + 鐘舵€佹寜閽紙閫氱煡鍙栭/鐑瑰埗瀹屾垚/寮€濮嬬児鍒讹級
- overflow-y 鏀逛负 visible
- **`prod-proc-serve.html`** 上餐监控
- 筛选栏新增「当前食堂」下拉
- **`prod-proc-serve.html`** 涓婇鐩戞帶
- 绛涢€夋爮鏂板銆屽綋鍓嶉鍫傘€嶄笅鎷?
- **`prod-proc-surplus.html`** 余量处置
- 筛选栏新增「当前食堂」下拉
- **`prod-proc-surplus.html`** 浣欓噺澶勭疆
- 绛涢€夋爮鏂板銆屽綋鍓嶉鍫傘€嶄笅鎷?
- **`prod-proc-stats.html`** 生产统计
- 新增页面标题行 + 食堂切换下拉(canteen-select 高亮样式)
- 移除两个 Tab 筛选栏中原有的「食堂」筛选项
- **`prod-proc-stats.html`** 鐢熶骇缁熻
- 鏂板椤甸潰鏍囬琛?+ 椋熷爞鍒囨崲涓嬫媺锛坈anteen-select 楂樹寒鏍峰紡锛?
- 绉婚櫎涓や釜 Tab 绛涢€夋爮涓師鏈夌殑銆岄鍫傘€嶇瓫閫夐」
### 增强 — 多页面交互优化与数据关联
### 澧炲己 鈥?澶氶〉闈氦浜掍紭鍖栦笌鏁版嵁鍏宠仈
- **`prod-clean-order.html`** 净菜订单
- 新增页面标题行 + 食堂切换下拉
- 筛选栏新增「预定配送时间」日期范围筛选
- 筛选栏新增「净菜类型」下拉(净菜包/餐品净菜包)
- 订单状态选项调整为:备货中/待配送/配送中/已完成
- 新增弹窗通用样式与表单网格布局
- **`prod-clean-order.html`** 鍑€鑿滆鍗?
- 鏂板椤甸潰鏍囬琛?+ 椋熷爞鍒囨崲涓嬫媺
- 绛涢€夋爮鏂板銆岄瀹氶厤閫佹椂闂淬€嶆棩鏈熻寖鍥寸瓫閫?
- 绛涢€夋爮鏂板銆屽噣鑿滅被鍨嬨€嶄笅鎷夛紙鍑€鑿滃寘/椁愬搧鍑€鑿滃寘锛?
- 璁㈠崟鐘舵€侀€夐」璋冩暣涓猴細澶囪揣涓?寰呴厤閫?閰嶉€佷腑/宸插畬鎴?
- 鏂板寮圭獥閫氱敤鏍峰紡涓庤〃鍗曠綉鏍煎竷灞€
- **`prod-qc-daily.html`** 食安监控
- 水电气表 Tab 移除「生成能耗日报」按钮
- 水/电/气三张能耗卡片右上角新增「✏️ 录入」入口,支持手动编辑当前余量与今日用量
- 新增页面标题行 + 食堂切换下拉
- 新增摄像头回放弹窗(含播放器、时间轴、分时段列表)
- 新增表单弹窗通用样式
- **`prod-qc-daily.html`** 椋熷畨鐩戞帶
- 姘寸數姘旇〃 Tab 绉婚櫎銆岀敓鎴愯兘鑰楁棩鎶ャ€嶆寜閽?
- 姘?鐢?姘斾笁寮犺兘鑰楀崱鐗囧彸涓婅鏂板銆屸湉锔?褰曞叆銆嶅叆鍙o紝鏀寔鎵嬪姩缂栬緫褰撳墠浣欓噺涓庝粖鏃ョ敤閲?
- 鏂板椤甸潰鏍囬琛?+ 椋熷爞鍒囨崲涓嬫媺
- 鏂板鎽勫儚澶村洖鏀惧脊绐楋紙鍚挱鏀惧櫒銆佹椂闂磋酱銆佸垎鏃舵鍒楄〃锛?
- 鏂板琛ㄥ崟寮圭獥閫氱敤鏍峰紡
- **`prod-proc-cabinet.html`** 净菜进柜
- 新增页面标题行 + 食堂切换下拉
- 筛选栏样式重构(独立圆角卡片)
- 移除 Tab 切换结构,改为左右分栏布局
- 新增标签/链接通用样式
- **`prod-proc-cabinet.html`** 鍑€鑿滆繘鏌?
- 鏂板椤甸潰鏍囬琛?+ 椋熷爞鍒囨崲涓嬫媺
- 绛涢€夋爮鏍峰紡閲嶆瀯锛堢嫭绔嬪渾瑙掑崱鐗囷級
- 绉婚櫎 Tab 鍒囨崲缁撴瀯锛屾敼涓哄乏鍙冲垎鏍忓竷灞€
- 鏂板鏍囩/閾炬帴閫氱敤鏍峰紡
- **`sup-clean-external.html`** 净菜外供
- 筛选栏新增「净菜类型」下拉
- 表格新增「净菜类型」「净菜/餐品」列
- 订单状态调整为:备货中/待配送/配送中/已完成
- 数据行新增餐品净菜包示例(宫保鸡丁、清蒸鱼、蒜蓉菠菜)
- 操作列按状态显示差异化按钮(确认收货/立即发货/备货完成)
- 新建订单弹窗新增「净菜类型」字段
- **`sup-clean-external.html`** 鍑€鑿滃渚?
- 绛涢€夋爮鏂板銆屽噣鑿滅被鍨嬨€嶄笅鎷?
- 琛ㄦ牸鏂板銆屽噣鑿滅被鍨嬨€嶃€屽噣鑿?椁愬搧銆嶅垪
- 璁㈠崟鐘舵€佽皟鏁翠负锛氬璐т腑/寰呴厤閫?閰嶉€佷腑/宸插畬鎴?
- 鏁版嵁琛屾柊澧為鍝佸噣鑿滃寘绀轰緥锛堝淇濋浮涓併€佹竻钂搁奔銆佽挏钃夎彔鑿滐級
- 鎿嶄綔鍒楁寜鐘舵€佹樉绀哄樊寮傚寲鎸夐挳锛堢‘璁ゆ敹璐?绔嬪嵆鍙戣揣/澶囪揣瀹屾垚锛?
- 鏂板缓璁㈠崟寮圭獥鏂板銆屽噣鑿滅被鍨嬨€嶅瓧娈?
- **`sup-clean-internal.html`** 净菜内供
- 筛选栏新增「净菜类型」下拉、订单状态调整
- 表格新增「净菜类型」「净菜/餐品」「预定配送时间」列
- 数据行新增餐品净菜包示例及更多数据
- 操作列按状态显示差异化按钮
- 新建申领弹窗新增「净菜类型」字段
- **`sup-clean-internal.html`** 鍑€鑿滃唴渚?
- 绛涢€夋爮鏂板銆屽噣鑿滅被鍨嬨€嶄笅鎷夈€佽鍗曠姸鎬佽皟鏁?
- 琛ㄦ牸鏂板銆屽噣鑿滅被鍨嬨€嶃€屽噣鑿?椁愬搧銆嶃€岄瀹氶厤閫佹椂闂淬€嶅垪
- 鏁版嵁琛屾柊澧為鍝佸噣鑿滃寘绀轰緥鍙婃洿澶氭暟鎹?
- 鎿嶄綔鍒楁寜鐘舵€佹樉绀哄樊寮傚寲鎸夐挳
- 鏂板缓鐢抽寮圭獥鏂板銆屽噣鑿滅被鍨嬨€嶅瓧娈?
- **`sup-in-clean.html`** 净菜加工
- 表格新增「关联单号」列(关联入库单号,如 NC-IN-001
- **`sup-in-clean.html`** 鍑€鑿滃姞宸?
- 琛ㄦ牸鏂板銆屽叧鑱斿崟鍙枫€嶅垪锛堝叧鑱斿叆搴撳崟鍙凤紝濡?NC-IN-001锛?
- **`sup-in-cleanin.html`** 净菜入库
- 表格新增「关联单号」列(关联加工批次号,如 PROC-001
- **`sup-in-cleanin.html`** 鍑€鑿滃叆搴?
- 琛ㄦ牸鏂板銆屽叧鑱斿崟鍙枫€嶅垪锛堝叧鑱斿姞宸ユ壒娆″彿锛屽 PROC-001锛?
+156 -36
View File
@@ -100,6 +100,8 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
.form-item input,.form-item select,.form-item textarea{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-item input:focus,.form-item select:focus{border-color:var(--primary);}
.form-item select{appearance: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='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;padding-right:28px;}
.form-item input[readonly]{background:#f8fafc;cursor:not-allowed;}
.form-item select:disabled{background:#f8fafc;color:var(--text-placeholder);cursor:not-allowed;}
/* 右侧抽屉 */
.drawer-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.45);z-index:1000;animation:modalFadeIn .2s ease;}
.drawer-overlay.closing{animation:modalFadeOut .2s ease forwards;}
@@ -182,12 +184,12 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<table>
<thead><tr><th>订单号</th><th>净菜类型</th><th>净菜/餐品</th><th>包装规格</th><th>需求份数</th><th>需求计量(kg)</th><th>订单状态</th><th>申领时间</th><th>预定配送时间</th><th>创建人</th><th>操作</th></tr></thead>
<tbody>
<tr><td>CO-001</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>菠菜</td><td>500g/袋</td><td>50</td><td>25</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 07:30</td><td>2026-04-22 10:00</td><td>张厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-002</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>猪排骨</td><td>2kg/盘</td><td>20</td><td>40</td><td><span class="tag tag-blue">配送中</span></td><td>2026-04-22 08:00</td><td>2026-04-22 10:30</td><td>李主管</td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="confirmReceive(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-001</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>菠菜-菠菜段</td><td>500g/袋</td><td>50</td><td>25</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 07:30</td><td>2026-04-22 10:00</td><td>张厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-002</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>猪排骨-排骨块</td><td>2kg/盘</td><td>20</td><td>40</td><td><span class="tag tag-blue">配送中</span></td><td>2026-04-22 08:00</td><td>2026-04-22 10:30</td><td>李主管</td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="confirmReceive(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-003</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>宫保鸡丁</td><td>标准份(500g</td><td>30</td><td>15</td><td><span class="tag tag-blue">配送中</span></td><td>2026-04-22 08:00</td><td>2026-04-22 10:30</td><td>李主管</td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="confirmReceive(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-005</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>清蒸鱼</td><td>标准份(500g</td><td>15</td><td>7.5</td><td><span class="tag tag-orange">待配送</span></td><td>2026-04-22 09:00</td><td>2026-04-22 11:00</td><td>王厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-006</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆土豆丝</td><td>500g/袋</td><td>40</td><td>20</td><td><span class="tag tag-gray">备货中</span></td><td>2026-04-22 09:15</td><td>2026-04-22 11:00</td><td>张厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-008</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>西兰花</td><td>500g/袋</td><td>30</td><td>15</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 10:00</td><td>2026-04-22 11:30</td><td>王厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-006</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆-土豆丝</td><td>500g/袋</td><td>40</td><td>20</td><td><span class="tag tag-gray">备货中</span></td><td>2026-04-22 09:15</td><td>2026-04-22 11:00</td><td>张厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>CO-008</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>西兰花-西兰花朵</td><td>500g/袋</td><td>30</td><td>15</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 10:00</td><td>2026-04-22 11:30</td><td>王厨师</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -208,27 +210,43 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<div class="form-grid">
<div class="form-item">
<div class="form-item__label">净菜类型<span class="required">*</span></div>
<select id="orderType" onchange="toggleOrderName()"><option value="">请选择</option><option value="nc">净菜包</option><option value="cp">餐品净菜包</option></select>
<select id="orderType" onchange="toggleOrderFields()"><option value="">请选择</option><option value="nc">净菜包</option><option value="cp">餐品净菜包</option></select>
</div>
<div class="form-item" id="orderNameNC">
<div class="form-item__label">净菜名称<span class="required">*</span></div>
<select><option value="">请选择净菜</option><option>菠菜</option><option>玉米(玉米粒)</option><option>猪排骨</option><option>鸡胸肉(鸡肉丝)</option><option>草鱼(鱼片)</option><option>土豆(土豆丝)</option><option>西兰花</option></select>
<div class="form-item" id="orderIngredientWrap" style="display:none;">
<div class="form-item__label">食材<span class="required">*</span></div>
<select id="orderIngredient" onchange="updateNcTypeOptions()">
<option value="">请选择食材</option>
<option value="土豆">土豆</option>
<option value="菠菜">菠菜</option>
<option value="玉米">玉米</option>
<option value="鸡胸肉">鸡胸肉</option>
<option value="草鱼">草鱼</option>
<option value="西兰花">西兰花</option>
</select>
</div>
<div class="form-item" id="orderNameCP" style="display:none;">
<div class="form-item" id="orderNcTypeWrap" style="display:none;">
<div class="form-item__label">净菜类型<span class="required">*</span></div>
<select id="orderNcType" disabled onchange="syncOrderMeasure()"><option value="">请先选择食材</option></select>
</div>
<div class="form-item" id="orderDishWrap" style="display:none;">
<div class="form-item__label">餐品名称<span class="required">*</span></div>
<select><option value="">请选择餐品</option><option>宫保鸡丁</option><option>清蒸鱼</option><option>蒜蓉菠菜</option><option>炒胡萝卜</option><option>红烧排骨</option></select>
<select id="orderDish" onchange="updateCpSpecOptions()"><option value="">请选择餐品</option><option>宫保鸡丁</option><option>清蒸鱼</option><option>蒜蓉菠菜</option><option>炒胡萝卜</option><option>红烧排骨</option></select>
</div>
<div class="form-item">
<div class="form-item" id="orderNcSpecWrap" style="display:none;">
<div class="form-item__label">包装规格<span class="required">*</span></div>
<input placeholder="如 500g/袋、2kg/盘">
<input id="orderNcSpec" inputmode="numeric" placeholder="请输入纯整数克数" oninput="sanitizeIntegerInput(this);syncOrderMeasure()">
</div>
<div class="form-item" id="orderCpSpecWrap" style="display:none;">
<div class="form-item__label">包装规格<span class="required">*</span></div>
<select id="orderCpSpec" onchange="syncOrderMeasure()"><option value="">请选择包装规格</option></select>
</div>
<div class="form-item">
<div class="form-item__label">需求份数<span class="required">*</span></div>
<input type="number" placeholder="请输入份数" min="1">
<input id="orderQty" inputmode="numeric" placeholder="请输入纯整数份数" oninput="sanitizeIntegerInput(this);syncOrderMeasure()">
</div>
<div class="form-item">
<div class="form-item__label">需求计量(kg)<span class="required">*</span></div>
<input type="number" placeholder="请输入数量" min="0.1" step="0.1">
<input id="orderMeasure" type="text" placeholder="自动计算" readonly>
</div>
<div class="form-item">
<div class="form-item__label">预定配送时间</div>
@@ -269,12 +287,114 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
</div>
<script>
// 弹窗开关
function openModal(id){document.getElementById(id).classList.add('show');}
function openModal(id){
if(id==='modal-order')resetOrderForm();
document.getElementById(id).classList.add('show');
}
function closeModal(id){document.getElementById(id).classList.remove('show');}
// 点击遮罩关闭
document.querySelectorAll('.modal-mask').forEach(function(m){m.addEventListener('click',function(e){if(e.target===m)m.classList.remove('show');});});
// 净菜类型切换:显示净菜名称或餐品名称
function toggleOrderName(){var v=document.getElementById('orderType').value;document.getElementById('orderNameNC').style.display=(v==='cp'?'none':'flex');document.getElementById('orderNameCP').style.display=(v==='cp'?'flex':'none');}
var ncTypeOptions={
'土豆':['土豆丝','土豆块','土豆泥'],
'菠菜':['菠菜段','菠菜碎'],
'玉米':['玉米粒','玉米段'],
'鸡胸肉':['鸡胸肉丝','鸡胸肉丁'],
'草鱼':['鱼片','鱼块'],
'西兰花':['西兰花朵','西兰花梗']
};
var cpSpecOptions={
'宫保鸡丁':[
{label:'标准份(500g',grams:500},
{label:'加量份(750g',grams:750}
],
'清蒸鱼':[
{label:'标准份(600g',grams:600},
{label:'大份(900g',grams:900}
],
'蒜蓉菠菜':[
{label:'标准份(400g',grams:400},
{label:'加量份(600g',grams:600}
],
'炒胡萝卜':[
{label:'标准份(300g',grams:300},
{label:'大份(500g',grams:500}
],
'红烧排骨':[
{label:'标准份(800g',grams:800},
{label:'家庭份(1200g',grams:1200}
]
};
function resetOrderForm(){
document.getElementById('orderType').value='nc';
document.getElementById('orderIngredient').value='';
document.getElementById('orderNcType').innerHTML='<option value="">请先选择食材</option>';
document.getElementById('orderNcType').disabled=true;
document.getElementById('orderDish').value='';
document.getElementById('orderCpSpec').innerHTML='<option value="">请选择包装规格</option>';
document.getElementById('orderCpSpec').disabled=true;
document.getElementById('orderNcSpec').value='';
document.getElementById('orderQty').value='';
document.getElementById('orderMeasure').value='';
toggleOrderFields();
}
function toggleOrderFields(){
var v=document.getElementById('orderType').value;
document.getElementById('orderIngredientWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('orderNcTypeWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('orderNcSpecWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('orderDishWrap').style.display=(v==='cp'?'flex':'none');
document.getElementById('orderCpSpecWrap').style.display=(v==='cp'?'flex':'none');
syncOrderMeasure();
}
function sanitizeIntegerInput(el){el.value=el.value.replace(/[^\d]/g,'');}
function updateNcTypeOptions(){
var ingredient=document.getElementById('orderIngredient').value;
var typeSelect=document.getElementById('orderNcType');
var options=ncTypeOptions[ingredient]||[];
typeSelect.innerHTML='<option value="">请选择净菜类型</option>';
options.forEach(function(text){
typeSelect.innerHTML+='<option value="'+text+'">'+text+'</option>';
});
typeSelect.disabled=!options.length;
typeSelect.value='';
syncOrderMeasure();
}
function updateCpSpecOptions(){
var dish=document.getElementById('orderDish').value;
var specSelect=document.getElementById('orderCpSpec');
var options=cpSpecOptions[dish]||[];
specSelect.innerHTML='<option value="">请选择包装规格</option>';
options.forEach(function(item){
specSelect.innerHTML+='<option value="'+item.grams+'">'+item.label+'</option>';
});
specSelect.disabled=!options.length;
specSelect.value='';
syncOrderMeasure();
}
function getCurrentSpecGrams(){
var type=document.getElementById('orderType').value;
if(type==='nc'){
var ncSpec=document.getElementById('orderNcSpec').value;
return ncSpec?parseInt(ncSpec,10):0;
}
if(type==='cp'){
var cpSpec=document.getElementById('orderCpSpec').value;
return cpSpec?parseInt(cpSpec,10):0;
}
return 0;
}
function syncOrderMeasure(){
var qty=parseInt(document.getElementById('orderQty').value||'0',10);
var grams=getCurrentSpecGrams();
var measureInput=document.getElementById('orderMeasure');
if(!qty||!grams){
measureInput.value='';
return;
}
var kg=(grams*qty/1000).toFixed(2);
measureInput.value=kg;
}
// 确认收货
var _confirmReceiveRow=null;
@@ -309,17 +429,17 @@ function closeDrawer(){
/* ========== 餐品食材数据 ========== */
var dishIngredients={
'宫保鸡丁':[
{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',type:'主材',amount:'120g'},
{trace:'NC-PROC-HUS-20260415-01',name:'花生',type:'辅材',amount:'20g'},
{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',type:'调料',amount:'5g'}
{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',cleanType:'鸡胸肉丁',type:'主材',amount:'120g'},
{trace:'NC-PROC-HUS-20260415-01',name:'花生',cleanType:'去皮花生仁',type:'辅材',amount:'20g'},
{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',cleanType:'干辣椒段',type:'调料',amount:'5g'}
],
'清蒸鱼':[
{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',type:'主材',amount:'100g'},
{trace:'NC-PROC-JPN-20260415-01',name:'姜片',type:'调料',amount:'适量'}
{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',cleanType:'草鱼块',type:'主材',amount:'100g'},
{trace:'NC-PROC-JPN-20260415-01',name:'姜',cleanType:'姜片',type:'调料',amount:'适量'}
],
'红烧排骨':[
{trace:'NC-PROC-ZPG-20260415-01',name:'猪排骨',type:'主材',amount:'200g'},
{trace:'NC-PROC-JYO-20260415-01',name:'酱油',type:'调料',amount:'15ml'}
{trace:'NC-PROC-ZPG-20260415-01',name:'猪排骨',cleanType:'排骨块',type:'主材',amount:'200g'},
{trace:'NC-PROC-JYO-20260415-01',name:'酱油',cleanType:'调味包',type:'调料',amount:'15ml'}
]
};
// 餐品净菜包对应的包装批次号
@@ -330,17 +450,17 @@ var dishBatch={
};
// 净菜包溯源码映射
var traceMap={
'菠菜':'NC-INT-BOCA-20260422-01',
'猪排骨':'NC-INT-ZLRJ-20260422-01',
'土豆土豆丝':'NC-INT-TDSI-20260422-01',
'西兰花':'NC-INT-XLHU-20260422-01'
'菠菜-菠菜段':'NC-INT-BOCA-20260422-01',
'猪排骨-排骨块':'NC-INT-ZLRJ-20260422-01',
'土豆-土豆丝':'NC-INT-TDSI-20260422-01',
'西兰花-西兰花朵':'NC-INT-XLHU-20260422-01'
};
// 净菜包对应的包装批次号
var ncBatch={
'菠菜':'BATCH-NC-20260422-01',
'猪排骨':'BATCH-NC-20260422-02',
'土豆土豆丝':'BATCH-NC-20260422-03',
'西兰花':'BATCH-NC-20260422-04'
'菠菜-菠菜段':'BATCH-NC-20260422-01',
'猪排骨-排骨块':'BATCH-NC-20260422-02',
'土豆-土豆丝':'BATCH-NC-20260422-03',
'西兰花-西兰花朵':'BATCH-NC-20260422-04'
};
/* ========== 详情抽屉(定制化渲染) ========== */
@@ -392,15 +512,15 @@ function showDetail(el){
var ings=dishIngredients[foodName]||[];
var tagCls={'主材':'tag-blue','辅材':'tag-green','调料':'tag-orange'};
html+='<div class="drawer-section"><div class="drawer-section__title">净菜包明细</div>';
html+='<table style="width:100%;border-collapse:collapse;margin-top:8px;"><thead><tr><th>食材溯源码</th><th>食材名称</th><th>分类</th><th>每份用量</th></tr></thead><tbody>';
html+='<div style="overflow-x:auto;"><table style="width:100%;min-width:560px;border-collapse:collapse;margin-top:8px;"><thead><tr><th>食材溯源码</th><th>食材名称</th><th>净菜类型</th><th>分类</th><th>每份用量</th></tr></thead><tbody>';
if(ings.length>0){
ings.forEach(function(i){
html+='<tr><td>'+i.trace+'</td><td>'+i.name+'</td><td><span class="tag '+(tagCls[i.type]||'')+'">'+i.type+'</span></td><td>'+i.amount+'</td></tr>';
html+='<tr><td>'+i.trace+'</td><td>'+i.name+'</td><td>'+(i.cleanType||'—')+'</td><td><span class="tag '+(tagCls[i.type]||'')+'">'+i.type+'</span></td><td>'+i.amount+'</td></tr>';
});
} else {
html+='<tr><td colspan="4" style="text-align:center;color:var(--text-placeholder);">暂无明细数据</td></tr>';
html+='<tr><td colspan="5" style="text-align:center;color:var(--text-placeholder);">暂无明细数据</td></tr>';
}
html+='</tbody></table></div>';
html+='</tbody></table></div></div>';
}
// 渲染抽屉
+6 -5
View File
@@ -527,17 +527,18 @@ function showDetail(el){
}else if(type==='餐品包'){
/* 餐品包类型:显示食材明细表 */
html+='<div class="drawer-section"><div class="drawer-section__title">食材明细</div>';
html+='<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;margin-top:4px;font-size:var(--font-sm)">';
html+='<div style="overflow-x:auto"><table style="width:100%;min-width:680px;border-collapse:collapse;margin-top:4px;font-size:var(--font-sm)">';
html+='<thead><tr><th style="background:#FAFAFA;padding:10px 12px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border)">溯源码</th>';
html+='<th style="background:#FAFAFA;padding:10px 12px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border)">食材名称</th>';
html+='<th style="background:#FAFAFA;padding:10px 12px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border)">净菜类型</th>';
html+='<th style="background:#FAFAFA;padding:10px 12px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border)">分类</th>';
html+='<th style="background:#FAFAFA;padding:10px 12px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border)">每份用量</th>';
html+='<th style="background:#FAFAFA;padding:10px 12px;text-align:left;font-weight:500;color:var(--text-secondary);border-bottom:1px solid var(--border)">合计用量</th></tr></thead>';
html+='<tbody>';
html+='<tr><td style="padding:10px 12px;border-bottom:1px solid var(--border);font-family:monospace;color:var(--primary)">NC-JD-0422-01</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">鸡丁</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)"><span class="tag tag-green">肉禽类</span></td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">150g</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">2.25kg</td></tr>';
html+='<tr><td style="padding:10px 12px;border-bottom:1px solid var(--border);font-family:monospace;color:var(--primary)">NC-HS-0422-02</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">花生</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)"><span class="tag tag-orange">干果类</span></td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">30g</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">0.45kg</td></tr>';
html+='<tr><td style="padding:10px 12px;border-bottom:1px solid var(--border);font-family:monospace;color:var(--primary)">NC-GJ-0422-03</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">干辣椒</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)"><span class="tag tag-red">调味料</span></td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">10g</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">0.15kg</td></tr>';
html+='<tr><td style="padding:10px 12px;font-family:monospace;color:var(--primary)">NC-HC-0422-04</td><td style="padding:10px 12px">黄瓜丁</td><td style="padding:10px 12px"><span class="tag tag-green">蔬菜类</span></td><td style="padding:10px 12px">80g</td><td style="padding:10px 12px">1.20kg</td></tr>';
html+='<tr><td style="padding:10px 12px;border-bottom:1px solid var(--border);font-family:monospace;color:var(--primary)">NC-JD-0422-01</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">鸡肉</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">鸡肉丁</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)"><span class="tag tag-green">肉禽类</span></td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">150g</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">2.25kg</td></tr>';
html+='<tr><td style="padding:10px 12px;border-bottom:1px solid var(--border);font-family:monospace;color:var(--primary)">NC-HS-0422-02</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">花生</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">去皮花生仁</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)"><span class="tag tag-orange">干果类</span></td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">30g</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">0.45kg</td></tr>';
html+='<tr><td style="padding:10px 12px;border-bottom:1px solid var(--border);font-family:monospace;color:var(--primary)">NC-GJ-0422-03</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">干辣椒</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">干辣椒段</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)"><span class="tag tag-red">调味料</span></td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">10g</td><td style="padding:10px 12px;border-bottom:1px solid var(--border)">0.15kg</td></tr>';
html+='<tr><td style="padding:10px 12px;font-family:monospace;color:var(--primary)">NC-HC-0422-04</td><td style="padding:10px 12px">黄瓜</td><td style="padding:10px 12px">黄瓜丁</td><td style="padding:10px 12px"><span class="tag tag-green">蔬菜类</span></td><td style="padding:10px 12px">80g</td><td style="padding:10px 12px">1.20kg</td></tr>';
html+='</tbody></table></div></div>';
}
+12 -5
View File
@@ -324,6 +324,13 @@ var recipeData={
]
};
var tagCls={'主材':'tag-blue','辅材':'tag-green','调料':'tag-orange'};
var cleanTypeMap={
'鸡胸肉':'鸡胸肉丁','花生米':'去皮花生仁','干辣椒':'干辣椒段','黄瓜丁':'黄瓜丁','葱姜蒜':'葱姜蒜末',
'番茄':'番茄块','鸡蛋':'蛋液','葱花':'葱花','五花肉':'五花肉块','酱油':'调味包','冰糖':'调味包',
'草鱼':'草鱼块','姜片':'姜片','葱丝':'葱丝','西兰花':'西兰花朵','胡萝卜':'胡萝卜片','大蒜':'蒜末',
'嫩豆腐':'豆腐块','肉末':'肉末','豆瓣酱':'调味包'
};
function getCleanTypeName(name){return cleanTypeMap[name]||name;}
/* ========== 弹窗开关(新建/编辑共用) ========== */
var _modalMode='create'; // 'create' | 'edit'
@@ -530,20 +537,20 @@ function showDetail(el){
// 食材明细表格
var ings=recipeData[dishName]||[];
html+='<div class="drawer-section"><div class="drawer-section__title">食材明细</div>';
html+='<table style="width:100%;border-collapse:collapse;margin-top:8px;"><thead><tr><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">溯源码</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">食材名称</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">分类</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">每份用量</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">合计用量</th></tr></thead><tbody>';
html+='<div style="overflow-x:auto;"><table style="width:100%;min-width:680px;border-collapse:collapse;margin-top:8px;"><thead><tr><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">溯源码</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">食材名称</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">净菜类型</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">分类</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">每份用量</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">合计用量</th></tr></thead><tbody>';
if(ings.length){
ings.forEach(function(i){
var total=i.amount*(qty||1);
html+='<tr><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+i.trace+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+i.name+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;"><span class="tag '+(tagCls[i.type]||'')+'">'+i.type+'</span></td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+i.amount+i.unit+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+total+i.unit+'</td></tr>';
html+='<tr><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+i.trace+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+i.name+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+getCleanTypeName(i.name)+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;"><span class="tag '+(tagCls[i.type]||'')+'">'+i.type+'</span></td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+i.amount+i.unit+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+total+i.unit+'</td></tr>';
});
} else {
html+='<tr><td colspan="5" style="padding:16px;text-align:center;color:#999;">暂无配方数据</td></tr>';
html+='<tr><td colspan="6" style="padding:16px;text-align:center;color:#999;">暂无配方数据</td></tr>';
}
html+='</tbody></table></div>';
html+='</tbody></table></div></div>';
Drawer.open('组配详情 — '+taskId,html);
}
</script>
</body>
</html>
</html>
+12 -5
View File
@@ -393,6 +393,13 @@ var recipeData={
]
};
var tagCls={'主材':'tag-blue','辅料':'tag-green','调料':'tag-orange'};
var cleanTypeMap={
'鸡胸肉':'鸡胸肉丁','花生米':'去皮花生仁','干辣椒':'干辣椒段','黄瓜丁':'黄瓜丁','葱姜蒜':'葱姜蒜末',
'番茄':'番茄块','鸡蛋':'蛋液','葱花':'葱花','五花肉':'五花肉块','酱油':'调味包','冰糖':'调味包',
'草鱼':'草鱼块','姜片':'姜片','葱丝':'葱丝','菠菜':'菠菜段','大蒜':'蒜末','西兰花':'西兰花朵',
'胡萝卜':'胡萝卜片','嫩豆腐':'豆腐块','肉末':'肉末','豆瓣酱':'调味包'
};
function getCleanTypeName(name){return cleanTypeMap[name]||name;}
/* 食材明细弹窗(动态渲染,溯源码可编辑) */
function openIngredientModal(name){
@@ -586,20 +593,20 @@ function showDetail(el){
// 食材明细表格
var ings=recipeData[dishName]||[];
bodyHtml+='<div class="drawer-section"><div class="drawer-section__title">食材明细</div>';
bodyHtml+='<table style="width:100%;border-collapse:collapse;margin-top:8px;"><thead><tr><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">溯源码</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">食材名称</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">分类</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">标准用量/份</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">实际用量/份</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">合计标准</th></tr></thead><tbody>';
bodyHtml+='<div style="overflow-x:auto;"><table style="width:100%;min-width:760px;border-collapse:collapse;margin-top:8px;"><thead><tr><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">溯源码</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">食材名称</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">净菜类型</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">分类</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">标准用量/份</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">实际用量/份</th><th style="padding:10px 12px;text-align:left;font-size:12px;color:#8c8c8c;border-bottom:1px solid #e8e8e8;">合计标准</th></tr></thead><tbody>';
if(ings.length){
ings.forEach(function(ig){
var total=ig.stdAmount*(qty||1);
bodyHtml+='<tr><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.trace+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.name+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;"><span class="tag '+(tagCls[ig.type]||'')+'">'+ig.type+'</span></td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.stdAmount+ig.unit+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.actualAmount+ig.unit+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+total+ig.unit+'</td></tr>';
bodyHtml+='<tr><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.trace+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.name+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+getCleanTypeName(ig.name)+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;"><span class="tag '+(tagCls[ig.type]||'')+'">'+ig.type+'</span></td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.stdAmount+ig.unit+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+ig.actualAmount+ig.unit+'</td><td style="padding:10px 12px;font-size:13px;border-bottom:1px solid #e8e8e8;">'+total+ig.unit+'</td></tr>';
});
} else {
bodyHtml+='<tr><td colspan="6" style="padding:16px;text-align:center;color:#999;">暂无配方数据</td></tr>';
bodyHtml+='<tr><td colspan="7" style="padding:16px;text-align:center;color:#999;">暂无配方数据</td></tr>';
}
bodyHtml+='</tbody></table></div>';
bodyHtml+='</tbody></table></div></div>';
Drawer.open('烹饪详情 — '+taskId, bodyHtml);
}
</script>
</body>
</html>
</html>
+145 -57
View File
@@ -101,6 +101,7 @@ textarea.form-control{height:auto;padding:8px 12px;resize:vertical;min-height:60
.form-divider{grid-column:1/-1;border:none;border-top:1px solid var(--border);margin:4px 0;}
/* 只读字段 */
.form-control[readonly]{background:#F5F5F5;color:var(--text-secondary);cursor:default;}
.form-control:disabled{background:#f8fafc;color:var(--text-placeholder);cursor:not-allowed;}
/* 右侧抽屉 */
.drawer-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.45);z-index:1000;animation:modalFadeIn .2s ease;}
.drawer-overlay.closing{animation:modalFadeOut .2s ease forwards;}
@@ -213,14 +214,14 @@ textarea.form-control{height:auto;padding:8px 12px;resize:vertical;min-height:60
<th>订单号</th><th>客户名称</th><th>净菜类型</th><th>净菜/餐品</th><th>包装规格</th><th>售卖份数</th><th>计量(kg)</th><th>单价(元/kg)</th><th>小计金额</th><th>下单时间</th><th>物流单号</th><th>订单状态</th><th>操作</th>
</tr></thead>
<tbody>
<tr><td>EXT-001</td><td>社区便民超市</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆土豆丝</td><td>5kg/箱</td><td>10</td><td>50</td><td>¥3.5</td><td>¥175</td><td>2026-04-22 08:00</td><td>SF1234567890</td><td><span class="tag tag-green">已完成</span></td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-001</td><td>社区便民超市</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆土豆块</td><td>5kg/箱</td><td>6</td><td>30</td><td>¥3.5</td><td>¥105</td><td>2026-04-22 08:00</td><td>SF1234567890</td><td><span class="tag tag-green">已完成</span></td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-002</td><td>周边餐饮企业</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>净猪里脊</td><td>1kg/箱</td><td>5</td><td>50</td><td>¥28</td><td>¥1,400</td><td>2026-04-22 09:30</td><td>SF9876543210</td><td><span class="tag tag-blue">配送中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReceiveConfirm(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-001</td><td>社区便民超市</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆-土豆丝</td><td>5kg/箱</td><td>10</td><td>50</td><td>¥3.5</td><td>¥175</td><td>2026-04-22 08:00</td><td>SF1234567890</td><td><span class="tag tag-green">已完成</span></td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-001</td><td>社区便民超市</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆-土豆块</td><td>5kg/箱</td><td>6</td><td>30</td><td>¥3.5</td><td>¥105</td><td>2026-04-22 08:00</td><td>SF1234567890</td><td><span class="tag tag-green">已完成</span></td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-002</td><td>周边餐饮企业</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>净猪里脊-里脊条</td><td>1kg/箱</td><td>5</td><td>50</td><td>¥28</td><td>¥1,400</td><td>2026-04-22 09:30</td><td>SF9876543210</td><td><span class="tag tag-blue">配送中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReceiveConfirm(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-003</td><td>周边餐饮企业</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>宫保鸡丁</td><td>标准份(500g</td><td>40</td><td>20</td><td>¥12</td><td>¥240</td><td>2026-04-22 09:30</td><td>SF9876543210</td><td><span class="tag tag-blue">配送中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReceiveConfirm(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-004</td><td>学校食堂</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>鸡肉鸡肉块</td><td>1kg/箱</td><td>6</td><td>60</td><td>¥2.0</td><td>¥120</td><td>2026-04-22 10:00</td><td></td><td><span class="tag tag-orange">待配送</span></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openShipModal('EXT-004')">立即发货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-004</td><td>学校食堂</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>西兰花</td><td>5kg/箱</td><td>8</td><td>40</td><td>¥4.5</td><td>¥180</td><td>2026-04-22 10:00</td><td></td><td><span class="tag tag-orange">待配送</span></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openShipModal('EXT-004')">立即发货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-005</td><td>职工家属区团购</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>清蒸鱼</td><td>标准份(500g</td><td>20</td><td>10</td><td>¥15</td><td>¥150</td><td>2026-04-22 10:30</td><td></td><td><span class="tag tag-gray">备货中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-006</td><td>职工家属区团购</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>蒜蓉菠菜</td><td>标准份(500g</td><td>30</td><td>15</td><td>¥8</td><td>¥120</td><td>2026-04-22 10:30</td><td></td><td><span class="tag tag-gray">备货中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-004</td><td>学校食堂</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>鸡肉-鸡肉块</td><td>1kg/箱</td><td>6</td><td>60</td><td>¥2.0</td><td>¥120</td><td>2026-04-22 10:00</td><td></td><td><span class="tag tag-orange">待配送</span></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openShipModal('EXT-004')">立即发货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-004</td><td>学校食堂</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>西兰花-西兰花朵</td><td>5kg/箱</td><td>8</td><td>40</td><td>¥4.5</td><td>¥180</td><td>2026-04-22 10:00</td><td></td><td><span class="tag tag-orange">待配送</span></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openShipModal('EXT-004')">立即发货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-005</td><td>职工家属区团购</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>清蒸鱼</td><td>标准份(600g</td><td>20</td><td>12</td><td>¥15</td><td>¥180</td><td>2026-04-22 10:30</td><td></td><td><span class="tag tag-gray">备货中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>EXT-006</td><td>职工家属区团购</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>蒜蓉菠菜</td><td>标准份(400g</td><td>30</td><td>12</td><td>¥8</td><td>¥96</td><td>2026-04-22 10:30</td><td></td><td><span class="tag tag-gray">备货中</span></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -245,22 +246,35 @@ textarea.form-control{height:auto;padding:8px 12px;resize:vertical;min-height:60
<div class="form-grid">
<div class="form-group">
<label class="form-label">净菜类型<span class="required">*</span></label>
<select class="form-control" id="orderType">
<select class="form-control" id="orderType" onchange="toggleCreateOrderFields()">
<option value="">请选择</option>
<option value="nc">净菜包</option>
<option value="cp">餐品净菜包</option>
</select>
</div>
<div class="form-group">
<label class="form-label">净菜名称<span class="required">*</span></label>
<select class="form-control" id="orderItem" onchange="onItemChange()">
<option value="">请选择净菜</option>
<option value="土豆(土豆丝)" data-price="3.5" data-pkg="5kg/箱">土豆(土豆丝)</option>
<option value="土豆(土豆块)" data-price="3.5" data-pkg="5kg/箱">土豆(土豆块)</option>
<option value="净猪里脊" data-price="28" data-pkg="1kg/箱">净猪里脊</option>
<option value="鸡肉(鸡肉块)" data-price="2.0" data-pkg="1kg/箱">鸡肉(鸡肉块)</option>
<option value="净西兰花" data-price="4.5" data-pkg="5kg/箱">净西兰花</option>
<option value="净胡萝卜" data-price="4.0" data-pkg="5kg/箱">净胡萝卜</option>
<div class="form-group" id="createIngredientWrap" style="display:none;">
<label class="form-label">食材<span class="required">*</span></label>
<select class="form-control" id="createIngredient" onchange="updateCreateNcTypes()">
<option value="">请选择食材</option>
<option value="土豆">土豆</option>
<option value="鸡肉">鸡肉</option>
<option value="净猪里脊">净猪里脊</option>
<option value="西兰花">西兰花</option>
<option value="胡萝卜">胡萝卜</option>
</select>
</div>
<div class="form-group" id="createNcTypeWrap" style="display:none;">
<label class="form-label">净菜类型<span class="required">*</span></label>
<select class="form-control" id="createNcType" disabled onchange="syncCreateOrderMeasure()"><option value="">请先选择食材</option></select>
</div>
<div class="form-group" id="createDishWrap" style="display:none;">
<label class="form-label">餐品名称<span class="required">*</span></label>
<select class="form-control" id="createDish" onchange="updateCreateCpSpecs()">
<option value="">请选择餐品</option>
<option value="宫保鸡丁">宫保鸡丁</option>
<option value="清蒸鱼">清蒸鱼</option>
<option value="蒜蓉菠菜">蒜蓉菠菜</option>
<option value="炒胡萝卜">炒胡萝卜</option>
</select>
</div>
<div class="form-group">
@@ -285,13 +299,17 @@ textarea.form-control{height:auto;padding:8px 12px;resize:vertical;min-height:60
</div>
</div>
</div>
<div class="form-group">
<div class="form-group" id="createNcSpecWrap" style="display:none;">
<label class="form-label">包装规格</label>
<input class="form-control" id="orderPkg" readonly placeholder="选择净菜后自动填充">
<input class="form-control" id="createNcSpec" inputmode="numeric" placeholder="请输入纯整数克数" oninput="sanitizeIntegerInput(this);syncCreateOrderMeasure()">
</div>
<div class="form-group" id="createCpSpecWrap" style="display:none;">
<label class="form-label">包装规格</label>
<select class="form-control" id="createCpSpec" onchange="syncCreateOrderMeasure()"><option value="">请选择包装规格</option></select>
</div>
<div class="form-group">
<label class="form-label">售卖份数<span class="required">*</span></label>
<input class="form-control" id="orderQty" type="number" min="1" value="1" oninput="calcOrder()">
<input class="form-control" id="orderQty" inputmode="numeric" placeholder="请输入纯整数份数" oninput="sanitizeIntegerInput(this);syncCreateOrderMeasure()">
</div>
<div class="form-group">
<label class="form-label">计量(kg)</label>
@@ -299,7 +317,7 @@ textarea.form-control{height:auto;padding:8px 12px;resize:vertical;min-height:60
</div>
<div class="form-group">
<label class="form-label">单价(元/kg)<span class="required">*</span></label>
<input class="form-control" id="orderPrice" type="number" min="0" step="0.1" placeholder="请输入单价" oninput="calcOrder()">
<input class="form-control" id="orderPrice" type="number" min="0" step="0.1" placeholder="请输入单价" oninput="syncCreateOrderMeasure()">
</div>
<div class="form-group">
<label class="form-label">小计金额</label>
@@ -450,10 +468,10 @@ var batchInfo={
'BATCH-DH-20260415-04':{dish:'炒胡萝卜',spec:'大份(800g',method:'保鲜盒',qty:'6',date:'2026-04-15'}
};
var dishIngredients={
'宫保鸡丁':[{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',type:'主材',amount:'120g'},{trace:'NC-PROC-HUS-20260415-01',name:'花生',type:'辅材',amount:'20g'},{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',type:'调料',amount:'5g'}],
'清蒸鱼':[{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',type:'主材',amount:'100g'},{trace:'NC-PROC-JPN-20260415-01',name:'姜片',type:'调料',amount:'适量'}],
'蒜蓉菠菜':[{trace:'NC-PROC-BOC-20260415-01',name:'净菠菜',type:'主材',amount:'120g'},{trace:'NC-PROC-DSN-20260415-01',name:'大蒜',type:'调料',amount:'8g'}],
'炒胡萝卜':[{trace:'NC-PROC-HLB-20260415-01',name:'净胡萝卜',type:'主材',amount:'260g'},{trace:'NC-PROC-CJG-20260415-01',name:'葱姜',type:'调料',amount:'适量'}]
'宫保鸡丁':[{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',cleanType:'鸡胸丁',type:'主材',amount:'120g'},{trace:'NC-PROC-HUS-20260415-01',name:'花生',cleanType:'花生仁',type:'辅材',amount:'20g'},{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',cleanType:'辣椒段',type:'调料',amount:'5g'}],
'清蒸鱼':[{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',cleanType:'鱼片',type:'主材',amount:'100g'},{trace:'NC-PROC-JPN-20260415-01',name:'姜片',cleanType:'姜片',type:'调料',amount:'适量'}],
'蒜蓉菠菜':[{trace:'NC-PROC-BOC-20260415-01',name:'净菠菜',cleanType:'菠菜段',type:'主材',amount:'120g'},{trace:'NC-PROC-DSN-20260415-01',name:'大蒜',cleanType:'蒜末',type:'调料',amount:'8g'}],
'炒胡萝卜':[{trace:'NC-PROC-HLB-20260415-01',name:'净胡萝卜',cleanType:'胡萝卜丝',type:'主材',amount:'260g'},{trace:'NC-PROC-CJG-20260415-01',name:'葱姜',cleanType:'姜丝',type:'调料',amount:'适量'}]
};
var dishBatch={
'宫保鸡丁':'BATCH-DH-20260415-01',
@@ -462,16 +480,30 @@ var dishBatch={
'炒胡萝卜':'BATCH-DH-20260415-04'
};
var traceMap={
'净菠菜':'NC-PROC-BOC-20260415-01',
'净胡萝卜':'NC-PROC-HLB-20260415-01',
'净土豆丝':'NC-PROC-TDS-20260415-01',
'净西兰花':'NC-PROC-XLH-20260415-01',
'净白菜':'NC-PROC-BCA-20260415-01',
'净黄瓜':'NC-PROC-HGU-20260415-01'
'土豆-土豆丝':'NC-PROC-TDS-20260415-01',
'土豆-土豆块':'NC-PROC-TDK-20260415-01',
'净猪里脊-里脊条':'NC-PROC-ZJL-20260415-01',
'鸡肉-鸡肉块':'NC-PROC-CJRK-20260422-01',
'西兰花-西兰花朵':'NC-PROC-XLH-20260422-01',
'胡萝卜-胡萝卜条':'NC-PROC-HLB-20260415-01'
};
var createNcTypes={
'土豆':['土豆丝','土豆块','土豆泥'],
'鸡肉':['鸡肉块','鸡肉丝'],
'净猪里脊':['里脊条','里脊片'],
'西兰花':['西兰花朵','西兰花梗'],
'胡萝卜':['胡萝卜条','胡萝卜丝']
};
var createCpSpecs={
'宫保鸡丁':[{label:'标准份(500g',grams:500},{label:'加量份(750g',grams:750}],
'清蒸鱼':[{label:'标准份(600g',grams:600},{label:'大份(900g',grams:900}],
'蒜蓉菠菜':[{label:'标准份(400g',grams:400},{label:'加量份(600g',grams:600}],
'炒胡萝卜':[{label:'标准份(300g',grams:300},{label:'大份(500g',grams:500}]
};
/* ========== 新建订单弹窗 ========== */
function openCreateOrder(){
resetCreateOrderForm();
document.getElementById('createOrderModal').classList.add('show');
}
function closeCreateOrder(){
@@ -495,26 +527,76 @@ function onOrderBatchChange(val){
panel.style.display='grid';
}
/* 选择净菜后自动填充包装规格并计算 */
function onItemChange(){
var sel=document.getElementById('orderItem');
var opt=sel.options[sel.selectedIndex];
var pkg=opt.getAttribute('data-pkg')||'';
document.getElementById('orderPkg').value=pkg;
calcOrder();
function resetCreateOrderForm(){
document.getElementById('orderType').value='nc';
document.getElementById('createIngredient').value='';
document.getElementById('createNcType').innerHTML='<option value="">请先选择食材</option>';
document.getElementById('createNcType').disabled=true;
document.getElementById('createDish').value='';
document.getElementById('createCpSpec').innerHTML='<option value="">请选择包装规格</option>';
document.getElementById('createCpSpec').disabled=true;
document.getElementById('createNcSpec').value='';
document.getElementById('orderQty').value='';
document.getElementById('orderWeight').value='';
document.getElementById('orderPrice').value='';
document.getElementById('orderSubtotal').value='';
toggleCreateOrderFields();
}
/* 计算计量和小计 */
function calcOrder(){
var sel=document.getElementById('orderItem');
var opt=sel.options[sel.selectedIndex];
var pkg=opt.getAttribute('data-pkg')||'';
var pkgKg=parseFloat(pkg)||0;
var qty=parseInt(document.getElementById('orderQty').value)||0;
var price=parseFloat(document.getElementById('orderPrice').value)||0;
var weight=pkgKg*qty;
document.getElementById('orderWeight').value=weight>0?weight:'';
var subtotal=price*weight;
function toggleCreateOrderFields(){
var v=document.getElementById('orderType').value;
document.getElementById('createIngredientWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('createNcTypeWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('createNcSpecWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('createDishWrap').style.display=(v==='cp'?'flex':'none');
document.getElementById('createCpSpecWrap').style.display=(v==='cp'?'flex':'none');
syncCreateOrderMeasure();
}
function sanitizeIntegerInput(el){el.value=el.value.replace(/[^\d]/g,'');}
function updateCreateNcTypes(){
var ingredient=document.getElementById('createIngredient').value;
var select=document.getElementById('createNcType');
var options=createNcTypes[ingredient]||[];
select.innerHTML='<option value="">请选择净菜类型</option>';
options.forEach(function(text){select.innerHTML+='<option value="'+text+'">'+text+'</option>';});
select.disabled=!options.length;
select.value='';
syncCreateOrderMeasure();
}
function updateCreateCpSpecs(){
var dish=document.getElementById('createDish').value;
var select=document.getElementById('createCpSpec');
var options=createCpSpecs[dish]||[];
select.innerHTML='<option value="">请选择包装规格</option>';
options.forEach(function(item){select.innerHTML+='<option value="'+item.grams+'">'+item.label+'</option>';});
select.disabled=!options.length;
select.value='';
syncCreateOrderMeasure();
}
function getCreateSpecGrams(){
var type=document.getElementById('orderType').value;
if(type==='nc'){
var val=document.getElementById('createNcSpec').value;
return val?parseInt(val,10):0;
}
if(type==='cp'){
var val2=document.getElementById('createCpSpec').value;
return val2?parseInt(val2,10):0;
}
return 0;
}
function syncCreateOrderMeasure(){
var qty=parseInt(document.getElementById('orderQty').value||'0',10);
var grams=getCreateSpecGrams();
var weightInput=document.getElementById('orderWeight');
var priceNum=parseFloat(document.getElementById('orderPrice').value)||0;
if(!qty||!grams){
weightInput.value='';
document.getElementById('orderSubtotal').value='';
return;
}
var weight=grams*qty/1000;
weightInput.value=weight.toFixed(2);
var subtotal=priceNum*weight;
document.getElementById('orderSubtotal').value=subtotal>0?'¥'+subtotal.toFixed(2):'';
}
@@ -522,10 +604,16 @@ function calcOrder(){
function submitOrder(){
var typeVal=document.getElementById('orderType').value;
if(!typeVal){alert('请选择净菜类型');return;}
var item=document.getElementById('orderItem').value;
if(!item){alert('请选择净菜名称');return;}
var price=document.getElementById('orderPrice').value;
if(!price){alert('请输入单价');return;}
if(typeVal==='nc'){
if(!document.getElementById('createIngredient').value){alert('请选择食材');return;}
if(!document.getElementById('createNcType').value){alert('请选择净菜类型');return;}
if(!document.getElementById('createNcSpec').value){alert('请输入包装规格');return;}
}else{
if(!document.getElementById('createDish').value){alert('请选择餐品');return;}
if(!document.getElementById('createCpSpec').value){alert('请选择包装规格');return;}
}
if(!document.getElementById('orderQty').value){alert('请输入售卖份数');return;}
if(!document.getElementById('orderPrice').value){alert('请输入单价');return;}
var customer=document.getElementById('orderCustomer').value.trim();
if(!customer){alert('请输入客户名称');return;}
alert('订单提交成功!');
@@ -667,10 +755,10 @@ function showDetail(el){
var ings=dishIngredients[foodName];
if(ings&&ings.length){
html+='<div class="drawer-section"><div class="drawer-section__title">净菜包明细</div>';
html+='<table class="ing-detail-table"><thead><tr><th>食材溯源码</th><th>食材名称</th><th>分类</th><th>每份用量</th></tr></thead><tbody>';
html+='<table class="ing-detail-table"><thead><tr><th>食材溯源码</th><th>食材名称</th><th>净菜类型</th><th>分类</th><th>每份用量</th></tr></thead><tbody>';
for(var i=0;i<ings.length;i++){
var tagClass=ings[i].type==='主材'?'tag-blue':ings[i].type==='辅材'?'tag-green':'tag-orange';
html+='<tr><td>'+ings[i].trace+'</td><td>'+ings[i].name+'</td><td><span class="status-tag '+tagClass+'">'+ings[i].type+'</span></td><td>'+ings[i].amount+'</td></tr>';
html+='<tr><td>'+ings[i].trace+'</td><td>'+ings[i].name+'</td><td>'+ings[i].cleanType+'</td><td><span class="status-tag '+tagClass+'">'+ings[i].type+'</span></td><td>'+ings[i].amount+'</td></tr>';
}
html+='</tbody></table></div>';
}
+135 -27
View File
@@ -96,6 +96,8 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
.form-item input,.form-item select,.form-item textarea{height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 12px;font-size:var(--font-sm);color:var(--text-primary);outline:none;background:#fff;}
.form-item input:focus,.form-item select:focus{border-color:var(--primary);}
.form-item select{appearance: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='%23999'/%3E%3C/svg%3E") no-repeat right 10px center;padding-right:28px;}
.form-item input[readonly]{background:#f8fafc;cursor:not-allowed;}
.form-item select:disabled{background:#f8fafc;color:var(--text-placeholder);cursor:not-allowed;}
/* 右侧抽屉 */
.drawer-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.45);z-index:1000;animation:modalFadeIn .2s ease;}
.drawer-overlay.closing{animation:modalFadeOut .2s ease forwards;}
@@ -190,13 +192,13 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<th>申领单号</th><th>申领场所</th><th>净菜类型</th><th>净菜/餐品</th><th>包装规格</th><th>申领份数</th><th>申领数量(kg)</th><th>订单状态</th><th>申领时间</th><th>预定配送时间</th><th>配送人</th><th>操作</th>
</tr></thead>
<tbody>
<tr><td>INT-001</td><td>一号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>菠菜</td><td>500g/袋</td><td>50</td><td>25</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 07:30</td><td>2026-04-22 09:00</td><td>李配送</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-001</td><td>一号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>玉米玉米粒</td><td>1kg/盒</td><td>20</td><td>20</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 07:30</td><td>2026-04-22 09:00</td><td>李配送</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-002</td><td>二号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>猪排骨</td><td>2kg/盘</td><td>20</td><td>40</td><td><span class="tag tag-blue">配送中</span></td><td>2026-04-22 08:00</td><td>2026-04-22 10:00</td><td>王配送</td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReceiveConfirm(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-001</td><td>一号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>菠菜-菠菜段</td><td>500g/袋</td><td>50</td><td>25</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 07:30</td><td>2026-04-22 09:00</td><td>李配送</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-001</td><td>一号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>玉米-玉米粒</td><td>1kg/盒</td><td>20</td><td>20</td><td><span class="tag tag-green">已完成</span></td><td>2026-04-22 07:30</td><td>2026-04-22 09:00</td><td>李配送</td><td class="td-actions"><span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-002</td><td>二号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>猪排骨-排骨块</td><td>2kg/盘</td><td>20</td><td>40</td><td><span class="tag tag-blue">配送中</span></td><td>2026-04-22 08:00</td><td>2026-04-22 10:00</td><td>王配送</td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReceiveConfirm(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-003</td><td>二号食堂厨房</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>宫保鸡丁</td><td>标准份(500g</td><td>30</td><td>15</td><td><span class="tag tag-blue">配送中</span></td><td>2026-04-22 08:00</td><td>2026-04-22 10:00</td><td>王配送</td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReceiveConfirm(this)">确认收货</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-004</td><td>三号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>草鱼鱼片</td><td>2kg/盘</td><td>20</td><td>40</td><td><span class="tag tag-orange">待配送</span></td><td>2026-04-22 08:30</td><td>2026-04-22 10:30</td><td></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openDeliverModal(this)">立即配送</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-004</td><td>三号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>草鱼-鱼片</td><td>2kg/盘</td><td>20</td><td>40</td><td><span class="tag tag-orange">待配送</span></td><td>2026-04-22 08:30</td><td>2026-04-22 10:30</td><td></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openDeliverModal(this)">立即配送</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-005</td><td>一号食堂厨房</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>清蒸鱼</td><td>标准份(500g</td><td>15</td><td>7.5</td><td><span class="tag tag-orange">待配送</span></td><td>2026-04-22 09:00</td><td>2026-04-22 11:00</td><td></td><td class="td-actions"><span class="link" style="color:var(--primary)" onclick="openDeliverModal(this)">立即配送</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-006</td><td>三号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆土豆丝</td><td>500g/袋</td><td>40</td><td>20</td><td><span class="tag tag-gray">备货中</span></td><td>2026-04-22 09:15</td><td>2026-04-22 11:30</td><td></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-006</td><td>三号食堂厨房</td><td><span class="tag tag-green">🥬 净菜包</span></td><td>土豆-土豆丝</td><td>500g/袋</td><td>40</td><td>20</td><td><span class="tag tag-gray">备货中</span></td><td>2026-04-22 09:15</td><td>2026-04-22 11:30</td><td></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>INT-007</td><td>二号食堂厨房</td><td><span class="tag tag-orange">🍱 餐品净菜包</span></td><td>蒜蓉菠菜</td><td>标准份(500g</td><td>25</td><td>12.5</td><td><span class="tag tag-gray">备货中</span></td><td>2026-04-22 09:30</td><td>2026-04-22 12:00</td><td></td><td class="td-actions"><span class="link" style="color:var(--success)" onclick="openReadyConfirm(this)">备货完成</span> <span class="link" onclick="showDetail(this)">详情</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
</tbody>
</table>
@@ -224,15 +226,37 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<div class="form-grid">
<div class="form-item">
<div class="form-item__label">净菜类型<span class="required">*</span></div>
<select id="claimType"><option value="">请选择</option><option value="nc">净菜包</option><option value="cp">餐品净菜包</option></select>
<select id="claimType" onchange="toggleClaimFields()"><option value="">请选择</option><option value="nc">净菜包</option><option value="cp">餐品净菜包</option></select>
</div>
<div class="form-item">
<div class="form-item__label">申领场所<span class="required">*</span></div>
<select><option value="">请选择</option><option>一号食堂厨房</option><option>二号食堂厨房</option><option>三号食堂厨房</option></select>
</div>
<div class="form-item">
<div class="form-item__label">净菜名称<span class="required">*</span></div>
<select><option value="">请选择净菜</option><option>菠菜</option><option>玉米(玉米粒)</option><option>猪排骨</option><option>鸡胸肉(鸡肉丝)</option><option>草鱼(鱼片)</option><option>土豆(土豆丝)</option></select>
<div class="form-item" id="claimIngredientWrap" style="display:none;">
<div class="form-item__label">食材<span class="required">*</span></div>
<select id="claimIngredient" onchange="updateClaimNcTypes()">
<option value="">请选择食材</option>
<option value="土豆">土豆</option>
<option value="菠菜">菠菜</option>
<option value="玉米">玉米</option>
<option value="猪排骨">猪排骨</option>
<option value="鸡胸肉">鸡胸肉</option>
<option value="草鱼">草鱼</option>
</select>
</div>
<div class="form-item" id="claimNcTypeWrap" style="display:none;">
<div class="form-item__label">净菜类型<span class="required">*</span></div>
<select id="claimNcType" disabled onchange="syncClaimMeasure()"><option value="">请先选择食材</option></select>
</div>
<div class="form-item" id="claimDishWrap" style="display:none;">
<div class="form-item__label">餐品名称<span class="required">*</span></div>
<select id="claimDish" onchange="updateClaimCpSpecs()">
<option value="">请选择餐品</option>
<option value="宫保鸡丁">宫保鸡丁</option>
<option value="清蒸鱼">清蒸鱼</option>
<option value="蒜蓉菠菜">蒜蓉菠菜</option>
<option value="炒胡萝卜">炒胡萝卜</option>
</select>
</div>
<div class="form-item">
<div class="form-item__label">包装批次号</div>
@@ -250,17 +274,21 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
</div>
</div>
</div>
<div class="form-item">
<div class="form-item" id="claimNcSpecWrap" style="display:none;">
<div class="form-item__label">包装规格<span class="required">*</span></div>
<input placeholder="如 500g/袋、1kg/盒">
<input id="claimNcSpec" inputmode="numeric" placeholder="请输入纯整数克数" oninput="sanitizeIntegerInput(this);syncClaimMeasure()">
</div>
<div class="form-item" id="claimCpSpecWrap" style="display:none;">
<div class="form-item__label">包装规格<span class="required">*</span></div>
<select id="claimCpSpec" onchange="syncClaimMeasure()"><option value="">请选择包装规格</option></select>
</div>
<div class="form-item">
<div class="form-item__label">申领份数<span class="required">*</span></div>
<input type="number" placeholder="请输入份数">
<input id="claimQty" inputmode="numeric" placeholder="请输入纯整数份数" oninput="sanitizeIntegerInput(this);syncClaimMeasure()">
</div>
<div class="form-item">
<div class="form-item__label">申领数量(kg)<span class="required">*</span></div>
<input type="number" placeholder="请输入数量">
<input id="claimMeasure" type="text" placeholder="自动计算" readonly>
</div>
<div class="form-item">
<div class="form-item__label">预定配送时间</div>
@@ -369,7 +397,10 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<script>
// 弹窗打开/关闭
function openModal(id){document.getElementById(id).classList.add('show');}
function openModal(id){
if(id==='modal-claim')resetClaimForm();
document.getElementById(id).classList.add('show');
}
function closeModal(id){document.getElementById(id).classList.remove('show');}
// 点击遮罩关闭
document.querySelectorAll('.modal-mask').forEach(m=>{
@@ -397,6 +428,83 @@ function onBatchChange(val){
panel.style.display='flex';
}
var claimNcTypes={
'土豆':['土豆丝','土豆块','土豆泥'],
'菠菜':['菠菜段','菠菜碎'],
'玉米':['玉米粒','玉米段'],
'猪排骨':['排骨块','排骨丁'],
'鸡胸肉':['鸡胸肉丝','鸡胸肉丁'],
'草鱼':['鱼片','鱼块']
};
var claimCpSpecs={
'宫保鸡丁':[{label:'标准份(500g',grams:500},{label:'加量份(750g',grams:750}],
'清蒸鱼':[{label:'标准份(600g',grams:600},{label:'大份(900g',grams:900}],
'蒜蓉菠菜':[{label:'标准份(400g',grams:400},{label:'加量份(600g',grams:600}],
'炒胡萝卜':[{label:'标准份(300g',grams:300},{label:'大份(500g',grams:500}]
};
function resetClaimForm(){
document.getElementById('claimType').value='nc';
document.getElementById('claimIngredient').value='';
document.getElementById('claimNcType').innerHTML='<option value="">请先选择食材</option>';
document.getElementById('claimNcType').disabled=true;
document.getElementById('claimDish').value='';
document.getElementById('claimCpSpec').innerHTML='<option value="">请选择包装规格</option>';
document.getElementById('claimCpSpec').disabled=true;
document.getElementById('claimNcSpec').value='';
document.getElementById('claimQty').value='';
document.getElementById('claimMeasure').value='';
toggleClaimFields();
}
function toggleClaimFields(){
var v=document.getElementById('claimType').value;
document.getElementById('claimIngredientWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('claimNcTypeWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('claimNcSpecWrap').style.display=(v==='nc'?'flex':'none');
document.getElementById('claimDishWrap').style.display=(v==='cp'?'flex':'none');
document.getElementById('claimCpSpecWrap').style.display=(v==='cp'?'flex':'none');
syncClaimMeasure();
}
function sanitizeIntegerInput(el){el.value=el.value.replace(/[^\d]/g,'');}
function updateClaimNcTypes(){
var ingredient=document.getElementById('claimIngredient').value;
var typeSelect=document.getElementById('claimNcType');
var options=claimNcTypes[ingredient]||[];
typeSelect.innerHTML='<option value="">请选择净菜类型</option>';
options.forEach(function(item){typeSelect.innerHTML+='<option value="'+item+'">'+item+'</option>';});
typeSelect.disabled=!options.length;
typeSelect.value='';
syncClaimMeasure();
}
function updateClaimCpSpecs(){
var dish=document.getElementById('claimDish').value;
var specSelect=document.getElementById('claimCpSpec');
var options=claimCpSpecs[dish]||[];
specSelect.innerHTML='<option value="">请选择包装规格</option>';
options.forEach(function(item){specSelect.innerHTML+='<option value="'+item.grams+'">'+item.label+'</option>';});
specSelect.disabled=!options.length;
specSelect.value='';
syncClaimMeasure();
}
function getClaimSpecGrams(){
var type=document.getElementById('claimType').value;
if(type==='nc'){
var ncSpec=document.getElementById('claimNcSpec').value;
return ncSpec?parseInt(ncSpec,10):0;
}
if(type==='cp'){
var cpSpec=document.getElementById('claimCpSpec').value;
return cpSpec?parseInt(cpSpec,10):0;
}
return 0;
}
function syncClaimMeasure(){
var qty=parseInt(document.getElementById('claimQty').value||'0',10);
var grams=getClaimSpecGrams();
var measureInput=document.getElementById('claimMeasure');
if(!qty||!grams){measureInput.value='';return;}
measureInput.value=(grams*qty/1000).toFixed(2);
}
// 备货完成弹窗 — 选择批次号回显信息
function onReadyBatchChange(val){
var panel=document.getElementById('readyBatchInfoPanel');
@@ -464,21 +572,21 @@ function doReady(){
/* ========== 餐品食材数据(与 sup-pkg-label 保持一致) ========== */
var dishIngredients={
'宫保鸡丁':[
{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',type:'主材',amount:'120g'},
{trace:'NC-PROC-HUS-20260415-01',name:'花生',type:'辅材',amount:'20g'},
{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',type:'调料',amount:'5g'}
{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',cleanType:'鸡胸丁',type:'主材',amount:'120g'},
{trace:'NC-PROC-HUS-20260415-01',name:'花生',cleanType:'花生仁',type:'辅材',amount:'20g'},
{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',cleanType:'辣椒段',type:'调料',amount:'5g'}
],
'清蒸鱼':[
{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',type:'主材',amount:'100g'},
{trace:'NC-PROC-JPN-20260415-01',name:'姜片',type:'调料',amount:'适量'}
{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',cleanType:'鱼片',type:'主材',amount:'100g'},
{trace:'NC-PROC-JPN-20260415-01',name:'姜片',cleanType:'姜片',type:'调料',amount:'适量'}
],
'蒜蓉菠菜':[
{trace:'NC-PROC-BOC-20260415-01',name:'净菠菜',type:'主材',amount:'120g'},
{trace:'NC-PROC-DSN-20260415-01',name:'大蒜',type:'调料',amount:'8g'}
{trace:'NC-PROC-BOC-20260415-01',name:'净菠菜',cleanType:'菠菜段',type:'主材',amount:'120g'},
{trace:'NC-PROC-DSN-20260415-01',name:'大蒜',cleanType:'蒜末',type:'调料',amount:'8g'}
],
'炒胡萝卜':[
{trace:'NC-PROC-HLB-20260415-01',name:'净胡萝卜',type:'主材',amount:'260g'},
{trace:'NC-PROC-CJG-20260415-01',name:'葱姜',type:'调料',amount:'适量'}
{trace:'NC-PROC-HLB-20260415-01',name:'净胡萝卜',cleanType:'胡萝卜丝',type:'主材',amount:'260g'},
{trace:'NC-PROC-CJG-20260415-01',name:'葱姜',cleanType:'姜丝',type:'调料',amount:'适量'}
]
};
// 餐品净菜包对应的包装批次号
@@ -537,7 +645,7 @@ function showDetail(el){
// 根据类型显示不同字段
if(!isCp){
// 净菜包 → 显示溯源码
var traceMap={'菠菜':'NC-INT-BOCA-20260422-01','玉米玉米粒':'NC-INT-BCAI-20260422-01','猪排骨':'NC-INT-ZLRJ-20260422-01','草鱼鱼片':'NC-INT-CAYO-20260422-01','土豆土豆丝':'NC-INT-TDSI-20260422-01'};
var traceMap={'菠菜-菠菜段':'NC-INT-BOCA-20260422-01','玉米-玉米粒':'NC-INT-BCAI-20260422-01','猪排骨-排骨块':'NC-INT-ZLRJ-20260422-01','草鱼-鱼片':'NC-INT-CAYO-20260422-01','土豆-土豆丝':'NC-INT-TDSI-20260422-01'};
html+='<div class="drawer-field"><div class="drawer-field__label">溯源码</div><div class="drawer-field__value">'+(traceMap[foodName]||'—')+'</div></div>';
} else {
// 餐品净菜包 → 显示包装批次号
@@ -558,13 +666,13 @@ function showDetail(el){
var ings=dishIngredients[foodName]||[];
var tagCls={'主材':'tag-blue','辅材':'tag-green','调料':'tag-orange'};
html+='<div class="drawer-section"><div class="drawer-section__title">净菜包明细</div>';
html+='<table class="ing-detail-table"><thead><tr><th>食材溯源码</th><th>食材名称</th><th>分类</th><th>每份用量</th></tr></thead><tbody>';
html+='<table class="ing-detail-table"><thead><tr><th>食材溯源码</th><th>食材名称</th><th>净菜类型</th><th>分类</th><th>每份用量</th></tr></thead><tbody>';
if(ings.length>0){
ings.forEach(function(i){
html+='<tr><td>'+i.trace+'</td><td>'+i.name+'</td><td><span class="tag '+(tagCls[i.type]||'')+'">'+i.type+'</span></td><td>'+i.amount+'</td></tr>';
html+='<tr><td>'+i.trace+'</td><td>'+i.name+'</td><td>'+i.cleanType+'</td><td><span class="tag '+(tagCls[i.type]||'')+'">'+i.type+'</span></td><td>'+i.amount+'</td></tr>';
});
} else {
html+='<tr><td colspan="4" style="text-align:center;color:var(--text-placeholder);">暂无明细数据</td></tr>';
html+='<tr><td colspan="5" style="text-align:center;color:var(--text-placeholder);">暂无明细数据</td></tr>';
}
html+='</tbody></table></div>';
}
+49 -15
View File
@@ -198,29 +198,29 @@ tbody td.td-actions{white-space:nowrap;}
<div class="table-card__content">
<table>
<thead><tr>
<th>加工批次号</th><th>溯源码</th><th>食材名称</th><th>净菜类型</th><th>加工步骤</th><th>毛菜重量(kg)</th><th>净菜量(kg)</th><th>出净率(%)</th><th>加工人员</th><th>开始时间</th><th>结束时间</th><th>质检结果</th><th>入库状态</th><th>操作</th>
<th>加工批次号</th><th>溯源码</th><th>食材名称</th><th>净菜类型</th><th>加工步骤</th><th>净菜需求量(kg)</th><th>毛菜重量(kg)</th><th>净菜产出量(kg)</th><th>出净率(%)</th><th>加工人员</th><th>开始时间</th><th>结束时间</th><th>质检结果</th><th>入库状态</th><th>操作</th>
</tr></thead>
<tbody>
<tr>
<td>PROC-001</td><td>NC-PROC-BOCA-20260415-01</td><td>土豆</td><td>土豆丝</td><td>去皮/切割</td><td>100</td><td>86</td><td>86.0</td><td>李加工</td><td>2026-04-15 08:00</td><td>2026-04-15 08:45</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-green">已入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-001</td><td>NC-PROC-BOCA-20260415-01</td><td>土豆</td><td>土豆丝</td><td>去皮/切割</td><td>80</td><td>100</td><td>86</td><td>86.0</td><td>李加工</td><td>2026-04-15 08:00</td><td>2026-04-15 08:45</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-green">已入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
<tr>
<td>PROC-002</td><td>NC-PROC-HLUB-20260415-01</td><td>土豆</td><td>土豆片</td><td>去皮/切割</td><td>140</td><td>120</td><td>85.7</td><td>王加工</td><td>2026-04-15 08:30</td><td>2026-04-15 09:20</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-002</td><td>NC-PROC-HLUB-20260415-01</td><td>土豆</td><td>土豆片</td><td>去皮/切割</td><td>115</td><td>140</td><td>120</td><td>85.7</td><td>王加工</td><td>2026-04-15 08:30</td><td>2026-04-15 09:20</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
<tr>
<td>PROC-003</td><td>NC-PROC-XGUO-20260415-01</td><td>土豆</td><td>土豆泥</td><td>去皮/切割</td><td>56</td><td>48</td><td>85.7</td><td>李加工</td><td>2026-04-15 09:00</td><td>2026-04-15 09:40</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-003</td><td>NC-PROC-XGUO-20260415-01</td><td>土豆</td><td>土豆泥</td><td>去皮/切割</td><td>45</td><td>56</td><td>48</td><td>85.7</td><td>李加工</td><td>2026-04-15 09:00</td><td>2026-04-15 09:40</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
<tr>
<td>PROC-004</td><td>NC-PROC-SJDOU-20260415-01</td><td>四季豆</td><td>段(5cm</td><td>清洗</td><td>60</td><td>52</td><td>86.7</td><td>张加工</td><td>2026-04-15 09:30</td><td>2026-04-15 10:00</td><td><span class="tag tag-orange">待处理</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-004</td><td>NC-PROC-SJDOU-20260415-01</td><td>四季豆</td><td>段(5cm</td><td>清洗</td><td>50</td><td>60</td><td>52</td><td>86.7</td><td>张加工</td><td>2026-04-15 09:30</td><td>2026-04-15 10:00</td><td><span class="tag tag-orange">待处理</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
<tr>
<td>PROC-005</td><td>NC-PROC-BCAI-20260415-01</td><td>白菜</td><td>整棵</td><td>清洗</td><td>80</td><td>70</td><td>87.5</td><td>张加工</td><td>2026-04-15 07:30</td><td>2026-04-15 08:10</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-005</td><td>NC-PROC-BCAI-20260415-01</td><td>白菜</td><td>整棵</td><td>清洗</td><td>65</td><td>80</td><td>70</td><td>87.5</td><td>张加工</td><td>2026-04-15 07:30</td><td>2026-04-15 08:10</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
<tr>
<td>PROC-006</td><td>NC-PROC-ZLRJ-20260415-01</td><td>猪里脊</td><td>丁(1.5cm</td><td>切割</td><td>80</td><td>76</td><td>95.0</td><td>王加工</td><td>2026-04-15 09:30</td><td>2026-04-15 09:55</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-006</td><td>NC-PROC-ZLRJ-20260415-01</td><td>猪里脊</td><td>丁(1.5cm</td><td>切割</td><td>72</td><td>80</td><td>76</td><td>95.0</td><td>王加工</td><td>2026-04-15 09:30</td><td>2026-04-15 09:55</td><td><span class="tag tag-green">合格</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="link" onclick="confirmGenStock(this)">生成入库单</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
<tr>
<td>PROC-007</td><td>NC-PROC-ZLRJ-20260415-02</td><td>猪里脊</td><td>条(4cm</td><td>切割</td><td>90</td><td>85</td><td>94.4</td><td>李加工</td><td>2026-04-15 10:00</td><td>2026-04-15 10:30</td><td><span class="tag tag-orange">待处理</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
<td>PROC-007</td><td>NC-PROC-ZLRJ-20260415-02</td><td>猪里脊</td><td>条(4cm</td><td>切割</td><td>80</td><td>90</td><td>85</td><td>94.4</td><td>李加工</td><td>2026-04-15 10:00</td><td>2026-04-15 10:30</td><td><span class="tag tag-orange">待处理</span></td><td><span class="tag tag-gray">未入库</span></td><td class="td-actions"><span class="link" onclick="openVideoModal()">查看视频</span> <span class="action-more"><span class="more-btn">更多 ▾</span><div class="dropdown"><a href="javascript:;" onclick="showDetail(this)">详情</a><a href="javascript:;" onclick="openModal()">编辑</a><a href="javascript:;" class="danger" onclick="if(confirm('确认删除该记录?')){}">删除</a></div></span></td>
</tr>
</tbody>
</table>
@@ -271,13 +271,25 @@ tbody td.td-actions{white-space:nowrap;}
</div>
<div class="modal-body">
<div class="form-grid">
<!-- 交互说明:先输入/选择溯源码 → 根据溯源码自动带出食材名称(只读)→ 根据食材名称带出净菜类型下拉选择) -->
<div class="form-item"><label>溯源码<span class="required">*</span></label><input type="text" placeholder="请输入或扫描溯源码"></div>
<div class="form-item"><label>食材名称</label><input type="text" placeholder="由溯源码自动带出或下拉选择" readonly style="background:#f5f5f5;"></div>
<div class="form-item"><label>净菜类型<span class="required">*</span></label><select><option>由食材名称带出</option><option>整棵</option><option>整朵</option><option></option><option></option><option></option><option></option><option></option><option></option><option></option><option>滚刀块</option><option>其他(备注说明)</option></select></div>
<!-- 交互说明:先选择食材名称 → 根据食材自动联动净菜类型下拉选 -->
<div class="form-item"><label>食材名称<span class="required">*</span></label>
<select id="foodSelect" onchange="onFoodChange()">
<option value="">请选择食材</option>
<option>土豆</option>
<option>四季豆</option>
<option>白菜</option>
<option>猪里脊</option>
</select>
</div>
<div class="form-item"><label>净菜类型<span class="required">*</span></label>
<select id="vegTypeSelect" disabled>
<option value="">请先选择食材</option>
</select>
</div>
<div class="form-item"><label>加工步骤<span class="required">*</span></label><select><option>请选择</option><option>清洗</option><option>去皮</option><option>切割</option><option>分拣</option><option>综合加工</option></select></div>
<div class="form-item"><label>净菜需求量(kg)<span class="required">*</span></label><input type="number" placeholder="请输入净菜需求量"></div>
<div class="form-item"><label>毛菜重量(kg)<span class="required">*</span></label><input type="number" placeholder="请输入毛菜重量"></div>
<div class="form-item"><label>净菜量(kg)</label><input type="number" placeholder="加工完成后填写"></div>
<div class="form-item"><label>净菜产出量(kg)</label><input type="number" placeholder="加工完成后填写"></div>
<div class="form-item"><label>出净率(%)</label><input type="text" placeholder="自动计算" readonly></div>
<div class="form-item"><label>加工人员<span class="required">*</span></label><input type="text" placeholder="请输入加工人员"></div>
<div class="form-item"><label>开始时间<span class="required">*</span></label><input type="datetime-local"></div>
@@ -319,18 +331,40 @@ document.getElementById('videoModal').addEventListener('click',function(e){if(e.
function openModal(){document.getElementById('modalOverlay').style.display='flex';}
function closeModal(){document.getElementById('modalOverlay').style.display='none';}
document.getElementById('modalOverlay').addEventListener('click',function(e){if(e.target===this)closeModal();});
/* 食材 → 净菜类型联动映射 */
var FOOD_VEG_MAP={
'土豆':['土豆丝','土豆片','土豆泥','土豆块'],
'四季豆':['段(5cm','整根'],
'白菜':['整棵','切段','切丝'],
'猪里脊':['丁(1.5cm','条(4cm','肉片','肉末']
};
function onFoodChange(){
var food=document.getElementById('foodSelect').value;
var vegSelect=document.getElementById('vegTypeSelect');
if(!food){
vegSelect.innerHTML='<option value="">请先选择食材</option>';
vegSelect.disabled=true;
return;
}
var types=FOOD_VEG_MAP[food]||[];
var html='<option value="">请选择净菜类型</option>';
types.forEach(function(t){html+='<option>'+t+'</option>';});
vegSelect.innerHTML=html;
vegSelect.disabled=false;
}
/* 生成入库单 */
var _stockRowData=null;
function confirmGenStock(el){
var tr=el.closest('tr');
var tds=tr.querySelectorAll('td');
/* 列序:0加工批次号 1溯源码 2食材名称 3净菜类型 4加工步骤 5毛菜重量 6净菜量 */
/* 列序:0加工批次号 1溯源码 2食材名称 3净菜类型 4加工步骤 5净菜需求量 6毛菜重量 7净菜产出量 */
_stockRowData={
batch:tds[0].textContent,
trace:tds[1].textContent,
food:tds[2].textContent,
cleanType:tds[3].textContent,
weight:tds[6].textContent
weight:tds[7].textContent
};
document.getElementById('confirmStockModal').style.display='flex';
}
+46 -7
View File
@@ -242,9 +242,8 @@ tbody td.td-actions{white-space:nowrap;}
<div class="modal-body">
<div class="form-grid">
<div class="form-item" id="fi-batch" style="display:none;"><label>关联加工批次</label><input id="f-batch" type="text" readonly style="background:#f5f5f5;"></div>
<div class="form-item"><label>溯源码<span class="required">*</span></label><input id="f-trace" type="text" placeholder="请输入溯源码"></div>
<div class="form-item"><label>食材名称</label><input id="f-food" type="text" placeholder="由溯源码自动带出" readonly style="background:#f5f5f5;"></div>
<div class="form-item"><label>净菜类型</label><input id="f-cleanType" type="text" placeholder="由溯源码自动带出" readonly style="background:#f5f5f5;"></div>
<div class="form-item"><label>食材名称<span class="required">*</span></label><select id="f-food" onchange="updateCleanTypeOptions()"><option>请选择</option></select></div>
<div class="form-item"><label>净菜类型<span class="required">*</span></label><select id="f-cleanType" disabled><option>请先选择食材</option></select></div>
<div class="form-item"><label>入库规格<span class="required">*</span></label><select><option>请选择</option><option>袋装/500g</option><option>袋装/400g</option><option>盒装/300g</option><option>散装/整棵</option><option>其他</option></select></div>
<div class="form-item"><label>入库数量<span class="required">*</span></label><input type="number" placeholder="请输入入库数量"></div>
<div class="form-item"><label>入库重量(kg)<span class="required">*</span></label><input id="f-weight" type="number" step="0.1" placeholder="请输入入库重量"></div>
@@ -295,10 +294,43 @@ var cleanAreaModalOptions={
'净菜柜':['8号柜-A01格口','8号柜-B03格口','9号柜-A02格口','10号柜-C01格口'],
'仓库':['A仓-蔬菜区-01','A仓-蔬菜区-02','A仓-蔬菜区-03','A仓-蔬菜区-04','B仓-肉类区-01','B仓-肉类区-02','B仓-肉类区-03','C仓-水产区-01','C仓-水产区-02']
};
var cleanFoodTypeOptions={
'土豆':['土豆丝','土豆块','土豆泥'],
'白菜':['整颗','白菜片','白菜段'],
'猪里脊':['丁(1.5cm','丝(0.8cm','片(2mm'],
'胡萝卜':['胡萝卜丝','胡萝卜块','胡萝卜片'],
'西兰花':['小朵','西兰花段','西兰花梗']
};
function renderSelectOptions(selectEl,placeholder,options){
if(!selectEl)return;
selectEl.innerHTML='<option>'+placeholder+'</option>'+options.map(function(item){return '<option>'+item+'</option>';}).join('');
}
function initCleanFoodOptions(){
renderSelectOptions(document.getElementById('f-food'),'请选择',Object.keys(cleanFoodTypeOptions));
}
function updateCleanTypeOptions(selectedType){
var foodSelect=document.getElementById('f-food');
var cleanTypeSelect=document.getElementById('f-cleanType');
var foodName=foodSelect.value;
var options=cleanFoodTypeOptions[foodName]||[];
cleanTypeSelect.disabled=!foodName||foodName==='请选择';
if(cleanTypeSelect.disabled){
cleanTypeSelect.innerHTML='<option>请先选择食材</option>';
return;
}
renderSelectOptions(cleanTypeSelect,'请选择',options);
if(selectedType&&options.indexOf(selectedType)>-1){
cleanTypeSelect.value=selectedType;
}
}
function findFoodByCleanType(cleanType){
for(var foodName in cleanFoodTypeOptions){
if(cleanFoodTypeOptions[foodName].indexOf(cleanType)>-1){
return foodName;
}
}
return '';
}
function updateCleanAreaFilterOptions(){
var storageType=document.getElementById('cleanStorageTypeFilter').value;
var options=storageType==='全部'
@@ -350,6 +382,8 @@ function openOutModal(id){document.getElementById('outModalOverlay').style.displ
function closeOutModal(){document.getElementById('outModalOverlay').style.display='none';}
document.getElementById('modalOverlay').addEventListener('click',function(e){if(e.target===this)closeModal();});
document.getElementById('outModalOverlay').addEventListener('click',function(e){if(e.target===this)closeOutModal();});
initCleanFoodOptions();
updateCleanTypeOptions();
updateCleanAreaFilterOptions();
/* 从净菜加工页跳转过来时,自动打开新增弹窗并填充数据 */
@@ -358,7 +392,6 @@ updateCleanAreaFilterOptions();
if(params.get('from')!=='clean')return;
/* 填充字段 */
var batch=params.get('batch')||'';
var trace=params.get('trace')||'';
var food=params.get('food')||'';
var cleanType=params.get('cleanType')||'';
var weight=params.get('weight')||'';
@@ -366,9 +399,15 @@ updateCleanAreaFilterOptions();
document.getElementById('fi-batch').style.display='';
document.getElementById('f-batch').value=batch;
}
if(trace) document.getElementById('f-trace').value=trace;
if(food) document.getElementById('f-food').value=food;
if(cleanType) document.getElementById('f-cleanType').value=cleanType;
if(!food&&cleanType){
food=findFoodByCleanType(cleanType);
}
if(food){
document.getElementById('f-food').value=food;
updateCleanTypeOptions(cleanType);
}else{
updateCleanTypeOptions();
}
if(weight) document.getElementById('f-weight').value=weight;
/* 自动打开弹窗 */
openModal();
+105 -30
View File
@@ -200,7 +200,7 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-primary" onclick="openModal('modal-nc')"> 新增净菜包</button> <button class="btn btn-primary"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button> <button class="btn btn-default"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button> <button class="btn btn-default">🖨️ 批量打印标签</button></div>
<div class="action-bar"><button class="btn btn-primary" onclick="openCleanPackModal()"> 新增净菜包</button> <button class="btn btn-primary"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button> <button class="btn btn-default"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button> <button class="btn btn-default">🖨️ 批量打印标签</button></div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">净菜包</div>
@@ -211,12 +211,12 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<th>包装批次号</th><th>溯源码</th><th>净菜名称</th><th>包装方式</th><th>包装规格</th><th>包装份数</th><th>包装日期</th><th>保质期至</th><th>存放温度(℃)</th><th>包装人</th><th>终端设备</th><th>操作</th>
</tr></thead>
<tbody>
<tr><td>BATCH-NC-20260415-01</td><td>NC-PROC-BOCA-20260415-01</td><td>土豆土豆丝</td><td><span class="tag tag-gray">真空袋</span></td><td>500g/袋</td><td>20</td><td>2026-04-15</td><td>2026-04-17</td><td>4.1</td><td>李包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-01</td><td>NC-PROC-BOCA-20260415-01</td><td>土豆土豆泥)</td><td><span class="tag tag-gray">真空袋</span></td><td>500g/袋</td><td>20</td><td>2026-04-15</td><td>2026-04-17</td><td>4.1</td><td>李包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-02</td><td>NC-PROC-HLUB-20260415-01</td><td>鸡肉(鸡爪)</td><td><span class="tag tag-gray">保鲜盒</span></td><td>1kg/盒</td><td>15</td><td>2026-04-15</td><td>2026-04-18</td><td>4.2</td><td>王包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-02</td><td>NC-PROC-HLUB-20260415-01</td><td>鸡肉(鸡肉块)</td><td><span class="tag tag-gray">保鲜盒</span></td><td>1kg/盒</td><td>15</td><td>2026-04-15</td><td>2026-04-18</td><td>4.2</td><td>王包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-03</td><td>NC-PROC-XGUO-20260415-01</td><td>菠菜</td><td><span class="tag tag-gray">散装托盘</span></td><td>2kg/盘</td><td>8</td><td>2026-04-15</td><td>2026-04-17</td><td>4.0</td><td>张包装</td><td>PKG-T02</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-04</td><td>NC-PROC-LAJP-20260415-01</td><td>豆腐(豆腐块)</td><td><span class="tag tag-gray">真空袋</span></td><td>1kg/袋</td><td>12</td><td>2026-04-15</td><td>2026-04-17</td><td>4.3</td><td>李包装</td><td>PKG-T02</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-01</td><td>NC-PROC-BOCA-20260415-01</td><td>土豆-土豆丝</td><td><span class="tag tag-gray">真空袋</span></td><td>500</td><td>20</td><td>2026-04-15</td><td>2026-04-17</td><td>4.1</td><td>李包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-01</td><td>NC-PROC-BOCA-20260415-01</td><td>土豆-土豆</td><td><span class="tag tag-gray">真空袋</span></td><td>500</td><td>20</td><td>2026-04-15</td><td>2026-04-17</td><td>4.1</td><td>李包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-02</td><td>NC-PROC-HLUB-20260415-01</td><td>土豆-土豆丝</td><td><span class="tag tag-gray">保鲜盒</span></td><td>1000</td><td>15</td><td>2026-04-15</td><td>2026-04-18</td><td>4.2</td><td>王包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-02</td><td>NC-PROC-HLUB-20260415-01</td><td>土豆-土豆丝</td><td><span class="tag tag-gray">保鲜盒</span></td><td>1000</td><td>15</td><td>2026-04-15</td><td>2026-04-18</td><td>4.2</td><td>王包装</td><td>PKG-T01</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-03</td><td>NC-PROC-XGUO-20260415-01</td><td>土豆-土豆丝</td><td><span class="tag tag-gray">散装托盘</span></td><td>2000</td><td>8</td><td>2026-04-15</td><td>2026-04-17</td><td>4.0</td><td>张包装</td><td>PKG-T02</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
<tr><td>BATCH-NC-20260415-04</td><td>NC-PROC-LAJP-20260415-01</td><td>土豆-土豆丝</td><td><span class="tag tag-gray">真空袋</span></td><td>1000</td><td>12</td><td>2026-04-15</td><td>2026-04-17</td><td>4.3</td><td>李包装</td><td>PKG-T02</td><td class="td-actions"><span class="link">查看视频</span> <span class="link">编辑</span> <span class="link" style="color:var(--danger)">删除</span></td></tr>
</tbody>
</table>
</div>
@@ -245,7 +245,7 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
<div class="action-bar"><button class="btn btn-primary" onclick="openModal('modal-dh')"> 新增餐品净菜包</button> <button class="btn btn-primary"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button> <button class="btn btn-default"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button> <button class="btn btn-default">🖨️ 批量打印标签</button></div>
<div class="action-bar"><button class="btn btn-primary" onclick="openDishPackModal()"> 新增餐品净菜包</button> <button class="btn btn-primary"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 10v2h10v-2M7 2v7M4.5 6.5L7 9l2.5-2.5" stroke="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>导出列表数据</button> <button class="btn btn-default"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><rect x="2" y="2" width="10" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4"/><path d="M4 5h6M4 7.5h4" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>查看导出任务</button> <button class="btn btn-default">🖨️ 批量打印标签</button></div>
<div class="table-card">
<div class="table-card__header">
<div class="table-card__title">餐品净菜包</div>
@@ -323,12 +323,12 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<div class="modal__body">
<div class="form-grid">
<div class="form-item">
<div class="form-item__label">溯源码<span class="required">*</span></div>
<input placeholder="输入溯源码可带出净菜名称">
<div class="form-item__label">食材名称<span class="required">*</span></div>
<select id="cleanFoodSelect" onchange="updateCleanPackTypeOptions()"><option value="">请选择食材</option></select>
</div>
<div class="form-item">
<div class="form-item__label">净菜名称<span class="required">*</span></div>
<select><option value="">请选择净菜</option><option>土豆(土豆丝)</option><option>土豆(土豆泥)</option><option>鸡肉(鸡爪)</option><option>鸡肉(鸡肉块)</option><option>菠菜</option><option>豆腐(豆腐块)</option></select>
<div class="form-item__label">净菜类型<span class="required">*</span></div>
<select id="cleanTypeSelect" disabled><option value="">选择食材</option></select>
</div>
<div class="form-item">
<div class="form-item__label">包装方式<span class="required">*</span></div>
@@ -336,7 +336,7 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
</div>
<div class="form-item">
<div class="form-item__label">包装规格<span class="required">*</span></div>
<input placeholder="如 500g/袋、1kg/盒">
<input id="cleanPackSpecInput" inputmode="numeric" placeholder="请输入纯整数数字">
</div>
<div class="form-item">
<div class="form-item__label">包装份数<span class="required">*</span></div>
@@ -399,11 +399,12 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
<div class="form-item full">
<div class="form-item__label">包含食材<span class="required">*</span></div>
<table class="ing-table" id="ingFormTable">
<thead><tr><th>食材溯源码</th><th>食材名称</th><th>分类</th><th>每份用量</th><th style="width:40px;">操作</th></tr></thead>
<thead><tr><th>食材溯源码</th><th>食材名称</th><th>净菜类型</th><th>分类</th><th>每份用量</th><th style="width:40px;">操作</th></tr></thead>
<tbody id="ingFormBody">
<tr>
<td><input placeholder="溯源码"></td>
<td><select><option value="">请选择</option><option>鸡胸肉</option></select></td>
<td><select onchange="updateIngredientCleanTypeOptions(this)"><option value="">请选择</option><option>鸡胸肉</option></select></td>
<td><select><option value="">请选择</option><option>鸡胸丁</option></select></td>
<td><select><option value="">请选择</option><option>主材</option><option>辅材</option><option>调料</option></select></td>
<td><input placeholder="如 120g"></td>
<td><button class="btn-row-del" onclick="removeIngRow(this)" title="删除"></button></td>
@@ -513,27 +514,74 @@ document.querySelectorAll('.modal-mask').forEach(m=>{
});
/* ========== 餐品食材数据 ========== */
var cleanPackFoodTypeOptions={
'土豆':['土豆丝','土豆块','土豆泥'],
'白菜':['白菜片','白菜段','整颗'],
'鸡肉':['鸡肉丁','鸡肉片','鸡肉块'],
'菠菜':['菠菜段','菠菜叶'],
'豆腐':['豆腐块','豆腐片']
};
var ingredientFoodTypeOptions={
'鸡胸肉':['鸡胸丁','鸡胸片'],
'花生':['花生碎','花生仁'],
'干辣椒':['辣椒段','辣椒圈'],
'草鱼':['鱼片','鱼块'],
'姜片':['姜片'],
'净菠菜':['菠菜段','菠菜叶'],
'大蒜':['蒜末','蒜片'],
'净胡萝卜':['胡萝卜丝','胡萝卜块','胡萝卜片'],
'葱姜':['葱段','姜丝']
};
var dishIngredients={
'宫保鸡丁':[
{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',type:'主材',amount:'120g'},
{trace:'NC-PROC-HUS-20260415-01',name:'花生',type:'辅材',amount:'20g'},
{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',type:'调料',amount:'5g'}
{trace:'NC-PROC-JXR-20260415-01',name:'鸡胸肉',cleanType:'鸡胸丁',type:'主材',amount:'120g'},
{trace:'NC-PROC-HUS-20260415-01',name:'花生',cleanType:'花生仁',type:'辅材',amount:'20g'},
{trace:'NC-PROC-GLJ-20260415-01',name:'干辣椒',cleanType:'辣椒段',type:'调料',amount:'5g'}
],
'清蒸鱼':[
{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',type:'主材',amount:'100g'},
{trace:'NC-PROC-JPN-20260415-01',name:'姜片',type:'调料',amount:'适量'}
{trace:'NC-PROC-CYU-20260415-01',name:'草鱼',cleanType:'鱼片',type:'主材',amount:'100g'},
{trace:'NC-PROC-JPN-20260415-01',name:'姜片',cleanType:'姜片',type:'调料',amount:'适量'}
],
'蒜蓉菠菜':[
{trace:'NC-PROC-BOC-20260415-01',name:'净菠菜',type:'主材',amount:'120g'},
{trace:'NC-PROC-DSN-20260415-01',name:'大蒜',type:'调料',amount:'8g'}
{trace:'NC-PROC-BOC-20260415-01',name:'净菠菜',cleanType:'菠菜段',type:'主材',amount:'120g'},
{trace:'NC-PROC-DSN-20260415-01',name:'大蒜',cleanType:'蒜末',type:'调料',amount:'8g'}
],
'炒胡萝卜':[
{trace:'NC-PROC-HLB-20260415-01',name:'净胡萝卜',type:'主材',amount:'260g'},
{trace:'NC-PROC-CJG-20260415-01',name:'葱姜',type:'调料',amount:'适量'}
{trace:'NC-PROC-HLB-20260415-01',name:'净胡萝卜',cleanType:'胡萝卜丝',type:'主材',amount:'260g'},
{trace:'NC-PROC-CJG-20260415-01',name:'葱姜',cleanType:'姜丝',type:'调料',amount:'适量'}
]
};
// 列表行对应的餐品名(与tbody行序一致)
var dishNames=['宫保鸡丁','宫保鸡丁','清蒸鱼','蒜蓉菠菜','炒胡萝卜'];
function renderOptions(selectEl, placeholder, options){
if(!selectEl)return;
selectEl.innerHTML='<option value="">'+placeholder+'</option>'+options.map(function(item){return '<option>'+item+'</option>';}).join('');
}
function initCleanPackOptions(){
renderOptions(document.getElementById('cleanFoodSelect'),'请选择食材',Object.keys(cleanPackFoodTypeOptions));
updateCleanPackTypeOptions();
}
function updateCleanPackTypeOptions(selectedType){
var foodSelect=document.getElementById('cleanFoodSelect');
var typeSelect=document.getElementById('cleanTypeSelect');
var food=foodSelect.value;
var options=cleanPackFoodTypeOptions[food]||[];
typeSelect.disabled=!food;
if(!food){
typeSelect.innerHTML='<option value="">请先选择食材</option>';
return;
}
renderOptions(typeSelect,'请选择净菜类型',options);
if(selectedType&&options.indexOf(selectedType)>-1){
typeSelect.value=selectedType;
}
}
function sanitizeIntegerInput(inputEl){
if(!inputEl)return;
inputEl.addEventListener('input',function(){
this.value=this.value.replace(/\D/g,'');
});
}
/* ========== 食材明细弹窗 ========== */
function showIngredients(idx){
@@ -549,27 +597,40 @@ function showIngredients(idx){
}
/* ========== 新增/编辑餐品净菜包弹窗 ========== */
function buildTypeOptions(foodName, selectedType){
var options=ingredientFoodTypeOptions[foodName]||[];
var html='<option value="">请选择</option>';
options.forEach(function(type){
html+='<option'+(selectedType===type?' selected':'')+'>'+type+'</option>';
});
return html;
}
// 构建食材行 HTML
function buildIngRow(trace,name,type,amount){
function buildIngRow(trace,name,cleanType,type,amount){
var foods=['鸡胸肉','花生','干辣椒','草鱼','姜片','净菠菜','大蒜','净胡萝卜','葱姜'];
var fOpts='<option value="">请选择</option>';
foods.forEach(function(f){fOpts+='<option'+(name===f?' selected':'')+'>'+f+'</option>';});
var types=['主材','辅材','调料'];
var tOpts='<option value="">请选择</option>';
types.forEach(function(t){tOpts+='<option'+(type===t?' selected':'')+'>'+t+'</option>';});
return '<tr><td><input value="'+(trace||'')+'" placeholder="溯源码"></td><td><select>'+fOpts+'</select></td><td><select>'+tOpts+'</select></td><td><input value="'+(amount||'')+'" placeholder="如 120g"></td><td><button class="btn-row-del" onclick="removeIngRow(this)" title="删除">✕</button></td></tr>';
return '<tr><td><input value="'+(trace||'')+'" placeholder="溯源码"></td><td><select onchange="updateIngredientCleanTypeOptions(this)">'+fOpts+'</select></td><td><select>'+buildTypeOptions(name,cleanType)+'</select></td><td><select>'+tOpts+'</select></td><td><input value="'+(amount||'')+'" placeholder="如 120g"></td><td><button class="btn-row-del" onclick="removeIngRow(this)" title="删除">✕</button></td></tr>';
}
function updateIngredientCleanTypeOptions(foodSelect, selectedType){
var row=foodSelect.closest('tr');
var cleanTypeSelect=row.children[2].querySelector('select');
cleanTypeSelect.innerHTML=buildTypeOptions(foodSelect.value, selectedType);
}
// 餐品选择变化 → 自动填充食材表格
function onDishChange(val){
var ings=dishIngredients[val]||[];
var tbody=document.getElementById('ingFormBody');
if(ings.length===0){tbody.innerHTML=buildIngRow('','','','');return;}
tbody.innerHTML=ings.map(function(i){return buildIngRow(i.trace,i.name,i.type,i.amount);}).join('');
if(ings.length===0){tbody.innerHTML=buildIngRow('','','','','');return;}
tbody.innerHTML=ings.map(function(i){return buildIngRow(i.trace,i.name,i.cleanType,i.type,i.amount);}).join('');
}
// 添加食材行
function addIngRow(){
var tbody=document.getElementById('ingFormBody');
tbody.insertAdjacentHTML('beforeend',buildIngRow('','','',''));
tbody.insertAdjacentHTML('beforeend',buildIngRow('','','','',''));
}
// 删除食材行(至少保留一行)
function removeIngRow(btn){
@@ -589,16 +650,30 @@ function openEditDh(el){
onDishChange(dishName);
openModal('modal-dh');
}
function openCleanPackModal(){
document.getElementById('cleanFoodSelect').selectedIndex=0;
updateCleanPackTypeOptions();
document.getElementById('cleanPackSpecInput').value='';
openModal('modal-nc');
}
function openDishPackModal(){
document.getElementById('modalDhTitle').textContent='新增餐品净菜包';
document.getElementById('dishSelect').selectedIndex=0;
document.getElementById('ingFormBody').innerHTML=buildIngRow('','','','','');
openModal('modal-dh');
}
// 新增时重置弹窗标题
var _origOpenModal=openModal;
openModal=function(id){
if(id==='modal-dh'){
document.getElementById('modalDhTitle').textContent='新增餐品净菜包';
document.getElementById('dishSelect').selectedIndex=0;
document.getElementById('ingFormBody').innerHTML=buildIngRow('','','','');
document.getElementById('ingFormBody').innerHTML=buildIngRow('','','','','');
}
_origOpenModal(id);
};
initCleanPackOptions();
sanitizeIntegerInput(document.getElementById('cleanPackSpecInput'));
</script>
</body>
</html>