diff --git a/web-admin/nutrition/doc/CHANGELOG.md b/web-admin/nutrition/doc/CHANGELOG.md index d1b07e3..b2a23b9 100644 --- a/web-admin/nutrition/doc/CHANGELOG.md +++ b/web-admin/nutrition/doc/CHANGELOG.md @@ -1,5 +1,16 @@ # 营养用餐管理端 CHANGELOG +## [2026-08-24] feat: 任务中心页重构(统计卡片/分段Tab/动态筛选) + 仓库页新增净菜包柜 + +- `sup-task-center.html` 任务中心重构: + - 顶部新增统计卡片(今日任务总数/待办任务/已完成任务/任务完成率) + - Tab 改为分段式样式,筛选栏与表头随 Tab 动态渲染 + - 毛菜加工任务改为按食材明细模式(需求数量/已加工/进度/截止时间),状态新增「进行中」 + - 净菜加工任务改为按食材+净菜类型的单行任务模式 +- `sup-warehouse.html` 仓库管理: + - 物品类型新增「净菜包」「净菜餐品包」,存储方式/货柜类型新增「净菜包柜」 + - 新增 1号净菜包柜格口数据与存取记录,货柜/物品类型标签样式统一映射(tag-purple 新增) + ## [2026-08-21] feat: 溯源链路详情卡片优化(去副标题/属性独占一行/时间并入详情/去重复溯源码) - `trace-timeline-ingredient.html` / `trace-timeline-dish.html` 溯源节点详情卡片: diff --git a/web-admin/nutrition/sup-task-center.html b/web-admin/nutrition/sup-task-center.html index 3bb5d0d..00e0528 100644 --- a/web-admin/nutrition/sup-task-center.html +++ b/web-admin/nutrition/sup-task-center.html @@ -41,11 +41,22 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei .sidebar-subgroup.open .sidebar-subgroup__body{display:block;} /* 主内容 */ .main{margin-left:240px;margin-top:56px;padding:24px;min-height:calc(100vh - 56px);} -/* Tab 切换栏 */ -.tabs{display:flex;gap:8px;margin-bottom:16px;background:#fff;border-radius:var(--radius-md);padding:8px 12px;box-shadow:var(--shadow-sm);} -.tab{padding:8px 20px;border-radius:var(--radius-sm);font-size:var(--font-sm);font-weight:500;cursor:pointer;color:var(--text-secondary);transition:all .2s;border:1px solid transparent;} -.tab:hover{color:var(--primary);} -.tab.active{color:var(--primary);background:var(--primary-light);border-color:var(--primary);} +/* 统计卡片 */ +.stats-row{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:16px;} +.stat-card{background:#fff;border-radius:var(--radius-md);padding:20px 24px;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:16px;} +.stat-card__icon{width:48px;height:48px;border-radius:var(--radius-md);display:flex;align-items:center;justify-content:center;font-size:24px;} +.stat-card__icon.blue{background:var(--primary-light);} +.stat-card__icon.green{background:#F6FFED;} +.stat-card__icon.orange{background:#FFF7E6;} +.stat-card__icon.red{background:#FFF1F0;} +.stat-card__info{display:flex;flex-direction:column;gap:4px;} +.stat-card__value{font-size:var(--font-xl);font-weight:700;color:var(--text-primary);} +.stat-card__label{font-size:var(--font-sm);color:var(--text-secondary);} +/* Tab 切换栏(分段式) */ +.tabs{display:flex;gap:0;margin-bottom:16px;background:#F0F2F5;border-radius:var(--radius-md);padding:4px;box-shadow:var(--shadow-sm);} +.tab{padding:8px 22px;border-radius:6px;font-size:var(--font-sm);font-weight:500;cursor:pointer;color:var(--text-secondary);transition:all .2s;white-space:nowrap;} +.tab:hover{color:var(--text-primary);} +.tab.active{color:var(--primary);background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.12);font-weight:600;} .tab__count{margin-left:6px;font-size:var(--font-xs);color:var(--text-placeholder);} .tab.active .tab__count{color:var(--primary);} /* 筛选栏 */ @@ -117,6 +128,19 @@ tbody tr:hover{background:#F8FBFF;} .detail-table th{background:#FAFAFA;padding:8px 12px;text-align:left;font-size:var(--font-xs);color:var(--text-secondary);font-weight:500;border-bottom:1px solid var(--border);} .detail-table td{padding:10px 12px;font-size:var(--font-sm);color:var(--text-primary);border-bottom:1px solid var(--border);} .detail-table tr:last-child td{border-bottom:none;} +.detail-table tfoot td{background:#FAFAFA;font-weight:600;border-top:1px solid var(--border);border-bottom:none;} +/* 模态框 */ +.modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.45);z-index:1000;display:flex;align-items:center;justify-content:center;animation:modalFadeIn .2s ease;} +.modal-overlay.closing{animation:modalFadeOut .2s ease forwards;} +.modal{background:#fff;border-radius:var(--radius-lg);box-shadow:var(--shadow-md);width:860px;max-width:92vw;max-height:86vh;display:flex;flex-direction:column;animation:modalZoomIn .2s ease;} +.modal-overlay.closing .modal{animation:modalZoomOut .2s ease forwards;} +@keyframes modalZoomIn{from{transform:scale(.96);opacity:0}to{transform:scale(1);opacity:1}} +@keyframes modalZoomOut{from{transform:scale(1);opacity:1}to{transform:scale(.96);opacity:0}} +.modal__header{display:flex;align-items:center;justify-content:space-between;padding:16px 24px;border-bottom:1px solid var(--border);flex-shrink:0;} +.modal__title{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);} +.modal__close{width:32px;height:32px;border:none;background:none;font-size:20px;cursor:pointer;border-radius:var(--radius-sm);color:var(--text-secondary);display:flex;align-items:center;justify-content:center;} +.modal__close:hover{background:#f5f5f5;color:var(--text-primary);} +.modal__body{padding:20px 24px 24px;overflow-y:auto;flex:1;} /* Toast */ .toast{position:fixed;top:80px;left:50%;transform:translateX(-50%) translateY(-20px);background:rgba(0,0,0,0.8);color:#fff;padding:12px 28px;border-radius:8px;font-size:13px;z-index:1200;opacity:0;visibility:hidden;transition:opacity .3s,transform .3s,visibility .3s;white-space:nowrap;pointer-events:none;} .toast.show{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0);} @@ -172,6 +196,14 @@ tbody tr:hover{background:#F8FBFF;}
+ +
+
📋
0
今日任务总数
+
0
待办任务
+
0
已完成任务
+
📈
0%
任务完成率
+
+
毛菜加工任务
@@ -180,16 +212,8 @@ tbody tr:hover{background:#F8FBFF;}
净菜包装任务
- -
-
-
-
-
-
- - -
+ +
@@ -204,9 +228,7 @@ tbody tr:hover{background:#F8FBFF;}
- - - +
任务编号关联单号任务内容摘要任务状态执行人生成时间截止时间完成时间操作
@@ -241,48 +263,47 @@ var TASK_TABS=[ { label:'毛菜加工任务', device:'毛菜加工秤', - statusOptions:['全部','待处理','已完成'], + mode:'raw', + statusOptions:['全部','待处理','进行中','已完成'], tasks:[ - { taskNo:'RW-20260613-001', refNo:'—', content:'黄瓜、土豆、西红柿 等3种食材', status:'待处理', statusType:'pending', executor:'—', createdAt:'2026-06-13 08:00', deadline:'2026-06-13 11:00', finishedAt:'—', + { taskNo:'RW-20260613-001', status:'已完成', statusType:'done', operator:'张三丰', device:'毛菜加工秤-01', taskDate:'2026-06-13', createdAt:'2026-06-13 08:00', finishedAt:'2026-06-13 09:45', detail:[ - { name:'黄瓜', spec:'需 2000g', state:'已录 2000g · 截止 10:00' }, - { name:'土豆', spec:'需 2500g', state:'已录 2500g · 截止 10:30' }, - { name:'西红柿', spec:'需 1750g', state:'已录 1750g · 截止 11:00' } + { itemNo:'MC-001', name:'黄瓜', required:20, actual:20, progress:'100%', deadline:'2026-06-13 10:00', finishedAt:'2026-06-13 09:30' }, + { itemNo:'MC-002', name:'土豆', required:25, actual:25, progress:'100%', deadline:'2026-06-13 10:30', finishedAt:'2026-06-13 09:45' }, + { itemNo:'MC-003', name:'西红柿', required:17.5, actual:17.5, progress:'100%', deadline:'2026-06-13 11:00', finishedAt:'2026-06-13 09:45' } ] }, - { taskNo:'RW-20260613-002', refNo:'—', content:'胡萝卜、小番茄 等2种食材', status:'待处理', statusType:'pending', executor:'—', createdAt:'2026-06-13 08:30', deadline:'2026-06-13 14:00', finishedAt:'—', + { taskNo:'RW-20260613-002', status:'进行中', statusType:'processing', operator:'李四', device:'毛菜加工秤-02', taskDate:'2026-06-13', createdAt:'2026-06-13 08:30', finishedAt:'—', detail:[ - { name:'胡萝卜', spec:'需 1000g', state:'已录 1000g · 截止 11:30' }, - { name:'小番茄', spec:'需 750g', state:'已录 750g · 截止 14:00' } + { itemNo:'MC-004', name:'胡萝卜', required:15, actual:12, progress:'80%', deadline:'2026-06-13 11:30', finishedAt:'—' }, + { itemNo:'MC-005', name:'小番茄', required:8, actual:8, progress:'100%', deadline:'2026-06-13 14:00', finishedAt:'2026-06-13 10:15' } ] }, - { taskNo:'RW-20260613-003', refNo:'—', content:'大白菜、娃娃菜、土豆 等3种食材', status:'已完成', statusType:'done', executor:'张三丰', createdAt:'2026-06-13 07:30', deadline:'2026-06-13 09:30', finishedAt:'2026-06-13 09:45', + { taskNo:'RW-20260613-003', status:'待处理', statusType:'pending', operator:'—', device:'—', taskDate:'2026-06-13', createdAt:'2026-06-13 07:30', finishedAt:'—', detail:[ - { name:'大白菜', spec:'需 4000g', state:'已录 4000g' }, - { name:'娃娃菜', spec:'需 1250g', state:'已录 1250g' }, - { name:'土豆', spec:'需 1500g', state:'已录 1500g' } + { itemNo:'MC-006', name:'大白菜', required:40, actual:0, progress:'0%', deadline:'2026-06-13 09:30', finishedAt:'—' }, + { itemNo:'MC-007', name:'娃娃菜', required:12.5, actual:0, progress:'0%', deadline:'2026-06-13 10:00', finishedAt:'—' }, + { itemNo:'MC-008', name:'土豆', required:15, actual:0, progress:'0%', deadline:'2026-06-13 10:30', finishedAt:'—' } + ] }, + { taskNo:'RW-20260613-004', status:'待处理', statusType:'pending', operator:'—', device:'—', taskDate:'2026-06-13', createdAt:'2026-06-13 09:00', finishedAt:'—', + detail:[ + { itemNo:'MC-009', name:'西兰花', required:20, actual:0, progress:'0%', deadline:'2026-06-13 15:00', finishedAt:'—' }, + { itemNo:'MC-010', name:'荷兰豆', required:6, actual:0, progress:'0%', deadline:'2026-06-13 15:30', finishedAt:'—' } ] } ] }, { label:'净菜加工任务', device:'净菜加工秤', + mode:'clean', statusOptions:['全部','待加工','进行中','已完成'], tasks:[ - { taskNo:'CW-20260617-001', refNo:'—', content:'土豆、胡萝卜、黄瓜 等3种食材', status:'进行中', statusType:'processing', executor:'赵六', createdAt:'2026-06-17 08:00', deadline:'2026-06-17 11:30', finishedAt:'—', - detail:[ - { name:'土豆', spec:'35×1×1mm · 长条 · 平刀', state:'已加工 3.2/5.0斤' }, - { name:'胡萝卜', spec:'20×1×1mm · 细丝 · 平刀', state:'已加工 1.5/2.0斤' }, - { name:'黄瓜', spec:'30×30×3mm · 圆片 · 平刀', state:'已加工 2.8/4.0斤' } - ] }, - { taskNo:'CW-20260617-002', refNo:'—', content:'大白菜、西红柿 等2种食材', status:'待加工', statusType:'pending', executor:'—', createdAt:'2026-06-17 10:00', deadline:'2026-06-17 14:00', finishedAt:'—', - detail:[ - { name:'大白菜', spec:'50×30×30mm · 宽段 · 平刀', state:'未加工' }, - { name:'西红柿', spec:'25×25×20mm · 楔形块 · 平刀', state:'未加工' } - ] }, - { taskNo:'CW-20260617-003', refNo:'—', content:'芹菜、洋葱 等2种食材', status:'已完成', statusType:'done', executor:'赵六', createdAt:'2026-06-17 07:30', deadline:'2026-06-17 09:00', finishedAt:'2026-06-17 09:15', - detail:[ - { name:'芹菜', spec:'40×10×10mm · 宽段 · 平刀', state:'已加工 3.0/3.0斤' }, - { name:'洋葱', spec:'30×2×2mm · 细丝 · 平刀', state:'已加工 2.0/2.0斤' } - ] } + { taskNo:'CW-20260617-001', status:'进行中', statusType:'processing', name:'土豆', cleanType:'土豆丝.细丝', processDate:'2026-06-17', required:5, actual:3.2, progress:'64%', device:'净菜加工秤-01', updatedAt:'2026-06-17 10:30', createdAt:'2026-06-17 08:00' }, + { taskNo:'CW-20260617-002', status:'进行中', statusType:'processing', name:'胡萝卜', cleanType:'胡萝卜丝.细丝', processDate:'2026-06-17', required:2, actual:1.5, progress:'75%', device:'净菜加工秤-01', updatedAt:'2026-06-17 10:45', createdAt:'2026-06-17 08:00' }, + { taskNo:'CW-20260617-003', status:'已完成', statusType:'done', name:'黄瓜', cleanType:'黄瓜片.圆片', processDate:'2026-06-17', required:4, actual:4, progress:'100%', device:'净菜加工秤-01', updatedAt:'2026-06-17 09:30', createdAt:'2026-06-17 07:30' }, + { taskNo:'CW-20260617-004', status:'待加工', statusType:'pending', name:'大白菜', cleanType:'白菜段.宽段', processDate:'2026-06-17', required:6, actual:0, progress:'0%', device:'—', updatedAt:'—', createdAt:'2026-06-17 10:00' }, + { taskNo:'CW-20260617-005', status:'待加工', statusType:'pending', name:'西红柿', cleanType:'番茄块.楔形块', processDate:'2026-06-17', required:3, actual:0, progress:'0%', device:'—', updatedAt:'—', createdAt:'2026-06-17 10:00' }, + { taskNo:'CW-20260617-006', status:'已完成', statusType:'done', name:'芹菜', cleanType:'芹菜段.宽段', processDate:'2026-06-17', required:3, actual:3, progress:'100%', device:'净菜加工秤-01', updatedAt:'2026-06-17 09:15', createdAt:'2026-06-17 07:30' }, + { taskNo:'CW-20260617-007', status:'已完成', statusType:'done', name:'洋葱', cleanType:'洋葱丝.细丝', processDate:'2026-06-17', required:2, actual:2, progress:'100%', device:'净菜加工秤-01', updatedAt:'2026-06-17 09:15', createdAt:'2026-06-17 07:30' }, + { taskNo:'CW-20260617-008', status:'待加工', statusType:'pending', name:'土豆', cleanType:'土豆片.圆片', processDate:'2026-06-17', required:3, actual:0, progress:'0%', device:'—', updatedAt:'—', createdAt:'2026-06-17 10:30' } ] }, { @@ -353,36 +374,188 @@ var currentTabIdx=0; /* ===== 渲染状态下拉选项(随 Tab 切换) ===== */ function renderStatusOptions(){ var sel=document.getElementById('fStatus'); + if(!sel) return; var opts=TASK_TABS[currentTabIdx].statusOptions; sel.innerHTML=opts.map(function(o){return '';}).join(''); } +/* ===== 各 Tab 搜索字段配置 ===== */ +var FILTER_DEFS={ + raw:['no','status','device','operator','date'], + clean:['no','status','date','device','name','cleanType'], + common:['no','status','operator','date'] +}; + +/* ===== 单个搜索项 HTML ===== */ +function filterFieldHtml(key){ + switch(key){ + case 'no': return '
'; + case 'status': return '
'; + case 'device': return '
'; + case 'date': return '
'; + case 'name': return '
'; + case 'cleanType': return '
'; + case 'operator': return '
'; + } + return ''; +} + +/* ===== 渲染搜索区(随 Tab 切换) ===== */ +function renderFilterBar(){ + var tab=TASK_TABS[currentTabIdx]; + var mode = tab.mode==='raw' ? 'raw' : (tab.mode==='clean' ? 'clean' : 'common'); + var keys=FILTER_DEFS[mode]; + var html=keys.map(filterFieldHtml).join('') + +'' + +''; + document.getElementById('filterBar').innerHTML=html; + renderStatusOptions(); + renderFilterSelects(); +} + +/* ===== 从当前 Tab 数据提取去重值 ===== */ +function distinctValues(field){ + var tab=TASK_TABS[currentTabIdx]; + var arr=[]; + tab.tasks.forEach(function(t){ + if(t[field] && t[field]!=='—' && arr.indexOf(t[field])===-1) arr.push(t[field]); + }); + return arr; +} + +/* ===== 填充下拉框选项(首项「全部」) ===== */ +function fillSelect(id, options){ + var sel=document.getElementById(id); + if(!sel) return; + sel.innerHTML=['全部'].concat(options).map(function(o){return '';}).join(''); +} + +/* ===== 净菜类型下拉框联动:按选中食材过滤 ===== */ +function updateCleanTypeOptions(){ + var nameSel=document.getElementById('fName'); + var typeSel=document.getElementById('fCleanType'); + if(!typeSel) return; + var tab=TASK_TABS[currentTabIdx]; + var selectedName = nameSel ? nameSel.value : '全部'; + var opts=['全部']; + tab.tasks.forEach(function(t){ + if(selectedName==='全部' || t.name===selectedName){ + if(opts.indexOf(t.cleanType)===-1) opts.push(t.cleanType); + } + }); + typeSel.innerHTML=opts.map(function(o){return '';}).join(''); +} + +/* ===== 食材名称变化 → 联动净菜类型 ===== */ +function onNameChange(){ + updateCleanTypeOptions(); +} + +/* ===== 渲染搜索下拉框(设备/食材/净菜类型) ===== */ +function renderFilterSelects(){ + fillSelect('fDevice', distinctValues('device')); + fillSelect('fName', distinctValues('name')); + updateCleanTypeOptions(); +} + +/* ===== 安全读取输入值 ===== */ +function val(id){ + var el=document.getElementById(id); + return el ? el.value.trim() : ''; +} + /* ===== 状态标签 HTML ===== */ function statusTag(statusType,text){ var cls=STATUS_TAG[statusType]||'tag-gray'; return ''+text+''; } +/* ===== 重量格式化 ===== */ +function fmtKg(kg){ return kg+'kg'; } +/* ===== 时间格式化(仅时分) ===== */ +function fmtTime(s){ return (s && s!=='—') ? s.split(' ')[1] : '—'; } + +/* ===== 渲染表头(随 Tab 切换) ===== */ +function renderThead(){ + var tab=TASK_TABS[currentTabIdx]; + var th; + if(tab.mode==='raw'){ + th=['序号','任务编号','任务状态','加工总量(kg)','任务明细','操作人','加工设备','任务日期','完成时间','创建时间','操作']; + }else if(tab.mode==='clean'){ + th=['序号','任务编号','任务状态','食材名称','净菜类型','加工日期','需求量','已加工重量','进度','加工设备','最后更新时间','创建时间','操作']; + }else{ + th=['任务编号','关联单号','任务内容摘要','任务状态','操作人','生成时间','截止时间','完成时间','操作']; + } + document.getElementById('taskThead').innerHTML=th.map(function(h){return ''+h+'';}).join(''); +} + +/* ===== 毛菜加工任务行 ===== */ +function rawRow(t,i){ + var vegCount=t.detail.length; + var totalKg=t.detail.reduce(function(s,d){return s+d.required;},0); + return '' + +''+(i+1)+'' + +''+t.taskNo+'' + +''+statusTag(t.statusType,t.status)+'' + +''+fmtKg(totalKg)+'' + +''+vegCount+'项' + +''+t.operator+'' + +''+t.device+'' + +''+t.taskDate+'' + +''+t.finishedAt+'' + +''+t.createdAt+'' + +'详情' + +''; +} + +/* ===== 净菜加工任务行 ===== */ +function cleanRow(t,i){ + return '' + +''+(i+1)+'' + +''+t.taskNo+'' + +''+statusTag(t.statusType,t.status)+'' + +''+t.name+'' + +''+t.cleanType+'' + +''+t.processDate+'' + +''+fmtKg(t.required)+'' + +''+(t.actual>0?fmtKg(t.actual):'—')+'' + +''+t.progress+'' + +''+t.device+'' + +''+(t.updatedAt||'—')+'' + +''+t.createdAt+'' + +'详情' + +''; +} + +/* ===== 通用任务行 ===== */ +function commonRow(t){ + return '' + +''+t.taskNo+'' + +''+t.refNo+'' + +''+t.content+'' + +''+statusTag(t.statusType,t.status)+'' + +''+t.executor+'' + +''+t.createdAt+'' + +''+t.deadline+'' + +''+t.finishedAt+'' + +'详情' + +''; +} + +/* ===== 渲染行(按模式分发) ===== */ +function renderRow(t,i){ + var tab=TASK_TABS[currentTabIdx]; + if(tab.mode==='raw') return rawRow(t,i); + if(tab.mode==='clean') return cleanRow(t,i); + return commonRow(t); +} + /* ===== 渲染表格 ===== */ function renderTable(){ + renderThead(); var tab=TASK_TABS[currentTabIdx]; var tbody=document.getElementById('taskTbody'); - var html=''; - tab.tasks.forEach(function(t){ - html+='' - +''+t.taskNo+'' - +''+t.refNo+'' - +''+t.content+'' - +''+statusTag(t.statusType,t.status)+'' - +''+t.executor+'' - +''+t.createdAt+'' - +''+t.deadline+'' - +''+t.finishedAt+'' - +'详情' - +''; - }); - tbody.innerHTML=html; - + tbody.innerHTML=tab.tasks.map(renderRow).join(''); document.getElementById('tableTitle').textContent=tab.label; document.getElementById('pageInfo').textContent='显示 '+tab.tasks.length+' 条'; } @@ -394,57 +567,83 @@ function renderTabCounts(){ }); } +/* ===== 渲染顶部统计卡片(全局汇总,不随 Tab 变化) ===== */ +function renderStats(){ + var total=0, done=0; + TASK_TABS.forEach(function(tab){ + total+=tab.tasks.length; + tab.tasks.forEach(function(t){ + if(t.statusType==='done') done++; + }); + }); + var pending=total-done; + var rate=total ? Math.round(done/total*100) : 0; + document.getElementById('statTotal').textContent=total; + document.getElementById('statPending').textContent=pending; + document.getElementById('statDone').textContent=done; + document.getElementById('statRate').textContent=rate+'%'; +} + /* ===== 切换 Tab ===== */ function switchTab(idx,el){ currentTabIdx=idx; document.querySelectorAll('.tab').forEach(function(t){t.classList.remove('active');}); el.classList.add('active'); - renderStatusOptions(); + renderFilterBar(); doReset(); - renderTable(); } -/* ===== 查询(简单前端过滤:任务编号/执行人关键字 + 状态精确匹配) ===== */ +/* ===== 查询(各 Tab 独立过滤字段) ===== */ function doQuery(){ var tab=TASK_TABS[currentTabIdx]; - var kwNo=document.getElementById('fTaskNo').value.trim(); - var kwExe=document.getElementById('fExecutor').value.trim(); - var status=document.getElementById('fStatus').value; + var mode = tab.mode==='raw' ? 'raw' : (tab.mode==='clean' ? 'clean' : 'common'); + var kwNo=val('fTaskNo'); + var status=val('fStatus'); + var kwDevice=val('fDevice'); + var kwOperator=val('fOperator'); + var kwName=val('fName'); + var kwCleanType=val('fCleanType'); + var dateStart=val('fDateStart'); + var dateEnd=val('fDateEnd'); var list=tab.tasks.filter(function(t){ if(kwNo && t.taskNo.indexOf(kwNo)===-1) return false; - if(kwExe && t.executor.indexOf(kwExe)===-1) return false; if(status && status!=='全部' && t.status!==status) return false; + if(kwDevice && kwDevice!=='全部' && t.device!==kwDevice) return false; + + if(mode==='raw'){ + if(kwOperator && (t.operator||'').indexOf(kwOperator)===-1) return false; + if(dateStart && t.taskDate < dateStart) return false; + if(dateEnd && t.taskDate > dateEnd) return false; + }else if(mode==='clean'){ + if(kwName && kwName!=='全部' && t.name!==kwName) return false; + if(kwCleanType && kwCleanType!=='全部' && t.cleanType!==kwCleanType) return false; + if(dateStart && t.processDate < dateStart) return false; + if(dateEnd && t.processDate > dateEnd) return false; + }else{ + if(kwOperator && (t.executor||'').indexOf(kwOperator)===-1) return false; + if(dateStart && t.createdAt.slice(0,10) < dateStart) return false; + if(dateEnd && t.createdAt.slice(0,10) > dateEnd) return false; + } return true; }); var tbody=document.getElementById('taskTbody'); - var html=''; - list.forEach(function(t){ - html+='' - +''+t.taskNo+'' - +''+t.refNo+'' - +''+t.content+'' - +''+statusTag(t.statusType,t.status)+'' - +''+t.executor+'' - +''+t.createdAt+'' - +''+t.deadline+'' - +''+t.finishedAt+'' - +'详情' - +''; - }); - tbody.innerHTML=html; + tbody.innerHTML=list.map(renderRow).join(''); document.getElementById('pageInfo').textContent='显示 '+list.length+' 条'; } /* ===== 重置 ===== */ function doReset(){ - document.getElementById('fTaskNo').value=''; - document.getElementById('fExecutor').value=''; - document.getElementById('fCreatedStart').value=''; - document.getElementById('fCreatedEnd').value=''; - var sel=document.getElementById('fStatus'); - sel.selectedIndex=0; + ['fTaskNo','fOperator','fDateStart','fDateEnd'].forEach(function(id){ + var el=document.getElementById(id); + if(el) el.value=''; + }); + ['fStatus','fDevice','fName','fCleanType'].forEach(function(id){ + var el=document.getElementById(id); + if(el) el.selectedIndex=0; + }); + updateCleanTypeOptions(); renderTable(); } @@ -485,18 +684,77 @@ function findTask(taskNo){ return null; } +/* ===== 毛菜加工食材明细表(任务明细弹窗与详情抽屉共用) ===== */ +function renderRawDetailTable(t){ + var rows='';var totalReq=0,totalActual=0; + t.detail.forEach(function(d){ + totalReq+=d.required; totalActual+=d.actual||0; + rows+='' + +''+d.itemNo+'' + +''+d.name+'' + +''+fmtKg(d.required)+'' + +''+(d.actual>0?fmtKg(d.actual):'—')+'' + +''+d.progress+'' + +''+fmtTime(d.deadline)+'' + +''+fmtTime(d.finishedAt)+'' + +''; + }); + return '' + +'' + +''+rows+'' + +'' + +'
食材编号食材名称需求量实际加工量进度截止时间完成时间
总计'+t.detail.length+'种'+fmtKg(totalReq)+''+(totalActual>0?fmtKg(totalActual):'—')+'
'; +} + function showDetail(taskNo){ var r=findTask(taskNo); if(!r) return; var tab=r.tab, t=r.task; + /* 毛菜加工任务:任务信息 + 食材列表 */ + if(tab.mode==='raw'){ + var rawFields= + '
任务编号
'+t.taskNo+'
' + +'
任务状态
'+statusTag(t.statusType,t.status)+'
' + +'
操作人
'+t.operator+'
' + +'
加工设备
'+t.device+'
' + +'
任务日期
'+t.taskDate+'
' + +'
创建时间
'+t.createdAt+'
' + +'
完成时间
'+t.finishedAt+'
'; + + var rawHtml='
任务信息
'+rawFields+'
' + +'
食材列表
'+renderRawDetailTable(t)+'
'; + + Drawer.open('任务详情 — '+t.taskNo, rawHtml); + return; + } + + /* 净菜加工任务:任务信息 */ + if(tab.mode==='clean'){ + var cleanFields= + '
任务编号
'+t.taskNo+'
' + +'
任务状态
'+statusTag(t.statusType,t.status)+'
' + +'
食材名称
'+t.name+'
' + +'
净菜类型
'+t.cleanType+'
' + +'
加工日期
'+t.processDate+'
' + +'
需求量
'+fmtKg(t.required)+'
' + +'
已加工重量
'+(t.actual>0?fmtKg(t.actual):'—')+'
' + +'
进度
'+t.progress+'
' + +'
加工设备
'+t.device+'
' + +'
最后更新时间
'+(t.updatedAt||'—')+'
' + +'
创建时间
'+t.createdAt+'
'; + + Drawer.open('任务详情 — '+t.taskNo, '
任务信息
'+cleanFields+'
'); + return; + } + /* 任务信息区 */ var fields= '
任务编号
'+t.taskNo+'
' +'
终端设备
'+tab.device+'
' +'
关联单号
'+t.refNo+'
' +'
任务状态
'+statusTag(t.statusType,t.status)+'
' - +'
执行人
'+t.executor+'
' + +'
操作人
'+t.executor+'
' +'
生成时间
'+t.createdAt+'
' +'
截止时间
'+t.deadline+'
' +'
完成时间
'+t.finishedAt+'
'; @@ -514,6 +772,32 @@ function showDetail(taskNo){ Drawer.open('任务详情 — '+t.taskNo, html); } +/* ===== 任务明细弹窗(毛菜加工) ===== */ +function showDetailList(taskNo){ + var r=findTask(taskNo); + if(!r) return; + var t=r.task; + Modal.open('任务明细 — '+t.taskNo, renderRawDetailTable(t)); +} + +/* ===== 模态框 ===== */ +var Modal={ + open:function(title,bodyHtml){ + this.close(); + var overlay=document.createElement('div'); + overlay.className='modal-overlay'; + overlay.innerHTML=''; + overlay.addEventListener('click',function(e){if(e.target===overlay)Modal.close();}); + document.body.appendChild(overlay); + }, + close:function(){ + var o=document.querySelector('.modal-overlay'); + if(!o)return; + o.classList.add('closing'); + setTimeout(function(){o.remove();},200); + } +}; + /* ===== Toast ===== */ function showToast(msg){ var el=document.getElementById('toast'); @@ -524,7 +808,8 @@ function showToast(msg){ } /* ===== 初始化 ===== */ -renderStatusOptions(); +renderStats(); +renderFilterBar(); renderTabCounts(); renderTable(); diff --git a/web-admin/nutrition/sup-warehouse.html b/web-admin/nutrition/sup-warehouse.html index a6b6f5e..07fcbd8 100644 --- a/web-admin/nutrition/sup-warehouse.html +++ b/web-admin/nutrition/sup-warehouse.html @@ -79,6 +79,7 @@ tbody tr:hover{background:#F8FBFF;} .tag-orange{background:#FFF7E6;color:var(--warning);} .tag-red{background:#FFF1F0;color:var(--danger);} .tag-gray{background:#F5F5F5;color:#999;} +.tag-purple{background:#F9F0FF;color:#722ED1;} .link{color:var(--primary);cursor:pointer;font-size:var(--font-sm);}.link:hover{color:#40a9ff;} .pagination{display:flex;align-items:center;justify-content:flex-end;padding:16px 24px;gap:8px;border-top:1px solid var(--border);} .pagination span{font-size:var(--font-sm);color:var(--text-secondary);} @@ -268,10 +269,10 @@ tbody tr:hover td.td-actions{background:#F8FBFF;}
- +
- +
@@ -302,11 +303,13 @@ tbody tr:hover td.td-actions{background:#F8FBFF;} 猪里脊净菜IN-20260415-003净菜柜3号净菜柜-C02格口8040402026-04-15 09:152026-04-19临期不足编辑 详情 草鱼毛菜IN-20260415-004仓库C仓-水产区-01600602026-04-15 09:452026-04-15已过期不足编辑 详情 胡萝卜毛菜IN-20260416-005仓库A仓-蔬菜区-0342004202026-04-16 11:002026-04-23正常充足编辑 详情 + 净土豆丝净菜包净菜包IN-20260422-031净菜包柜1号净菜包柜-A02格口2510152026-04-22 09:152026-04-25正常充足编辑 详情 + 土豆烧肉餐品包净菜餐品包IN-20260422-032净菜包柜1号净菜包柜-B01格口186122026-04-22 10:302026-04-24临期充足编辑 详情