diff --git a/web-admin/nutrition/din-terminal.html b/web-admin/nutrition/din-terminal.html index 8b62db8..754e123 100644 --- a/web-admin/nutrition/din-terminal.html +++ b/web-admin/nutrition/din-terminal.html @@ -821,10 +821,20 @@ function renderOvTabBody(key){ /* ===== 表头列筛选(餐线营养秤四个 Tab 复用) ===== */ var SCALE_FILTERS={status:{},face:{},weight:{},log:{}}; -/* 日期范围筛选(标题下方筛选栏,status/face/weight 三个 Tab 使用) */ -var SCALE_DATE_RANGE={status:{from:'',to:''},face:{from:'',to:''},weight:{from:'',to:''}}; +/* 日期范围筛选(标题下方筛选栏,status/face/weight 三个 Tab 使用,默认当天) */ +function scaleTodayRange(){ + var d=new Date(); + var pad=function(n){return (n<10?'0':'')+n;}; + var day=d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate()); + return {from:day+'T00:00',to:day+'T23:59'}; +} +var SCALE_TODAY=scaleTodayRange(); +var SCALE_DATE_RANGE={status:{from:SCALE_TODAY.from,to:SCALE_TODAY.to},face:{from:SCALE_TODAY.from,to:SCALE_TODAY.to},weight:{from:SCALE_TODAY.from,to:SCALE_TODAY.to}}; /* 各 Tab 用于日期范围筛选的时间字段 */ var SCALE_TIME_FIELD={status:'time',face:'start',weight:'start'}; +/* 分页:各 Tab 当前页码与每页条数 */ +var SCALE_PAGE={status:1,face:1,weight:1,log:1}; +var SCALE_PAGE_SIZE=5; /* 重量变化数据展示样式:table 表格 / chart 折线图 */ var SCALE_WEIGHT_VIEW='table'; /* 识别点状态配色(折线图图例与数据点) */ @@ -838,8 +848,7 @@ var SCALE_COLS={ ], face:[ {key:'start',label:'开始时间',field:'start',type:'datetime'}, - {key:'end',label:'结束时间',field:'end',type:'datetime'}, - {key:'status',label:'状态',field:'status'} + {key:'end',label:'结束时间',field:'end',type:'datetime'} ], weight:[ {key:'start',label:'日期/时间',field:'start',type:'datetime'}, @@ -911,6 +920,37 @@ function getFilteredScaleRows(tabKey){ return true; }); } +/* 分页:取某 Tab 当前页数据(含总条数与总页数) */ +function getScalePageRows(tabKey){ + var all=getFilteredScaleRows(tabKey); + var total=all.length; + var totalPages=Math.max(1,Math.ceil(total/SCALE_PAGE_SIZE)); + var page=SCALE_PAGE[tabKey]||1; + if(page>totalPages)page=totalPages; + if(page<1)page=1; + SCALE_PAGE[tabKey]=page; + var start=(page-1)*SCALE_PAGE_SIZE; + return {rows:all.slice(start,start+SCALE_PAGE_SIZE),total:total,page:page,totalPages:totalPages}; +} +/* 分页控件:共 N 条 + 上一页/页码/下一页 */ +function renderScalePagination(tabKey,total){ + var totalPages=Math.max(1,Math.ceil(total/SCALE_PAGE_SIZE)); + if(total===0)return ''; + var page=SCALE_PAGE[tabKey]||1; + if(page>totalPages)page=totalPages; + var html='
共 '+total+' 条'; + html+=''; + for(var i=1;i<=totalPages;i++){ + html+=''; + } + html+='
'; + return html; +} +function goScalePage(tabKey,page){ + SCALE_PAGE[tabKey]=page; + var body=document.getElementById('scaleSubBody'); + if(body)body.innerHTML=renderScaleSubBody(SCALE_SUB_TAB); +} /* 时间戳截断到分钟并统一为 datetime-local 格式(YYYY-MM-DDTHH:mm) */ function normalizeMinute(ts){ return String(ts).slice(0,16).replace(' ','T'); @@ -983,6 +1023,7 @@ function closeThFilter(){ function pickThFilter(tabKey,colKey,val){ if(!SCALE_FILTERS[tabKey])SCALE_FILTERS[tabKey]={}; SCALE_FILTERS[tabKey][colKey]=val; + SCALE_PAGE[tabKey]=1; closeThFilter(); var body=document.getElementById('scaleSubBody'); if(body)body.innerHTML=renderScaleSubBody(SCALE_SUB_TAB); @@ -998,7 +1039,7 @@ function escapeAttr(s){ var SCALE_SUB_TABS=[ {key:'status',name:'设备状态监控'}, {key:'weight',name:'重量变化数据'}, - {key:'face',name:'人脸识别数据'}, + {key:'face',name:'视频数据'}, {key:'log',name:'运行日志'} ]; var SCALE_SUB_TAB='status'; @@ -1056,8 +1097,8 @@ function renderScaleFilterBar(tabKey){ function applyScaleFilter(tabKey,reset){ if(!SCALE_DATE_RANGE[tabKey])SCALE_DATE_RANGE[tabKey]={from:'',to:''}; if(reset){ - SCALE_DATE_RANGE[tabKey].from=''; - SCALE_DATE_RANGE[tabKey].to=''; + SCALE_DATE_RANGE[tabKey].from=SCALE_TODAY.from; + SCALE_DATE_RANGE[tabKey].to=SCALE_TODAY.to; if(tabKey==='status'){ if(!SCALE_FILTERS.status)SCALE_FILTERS.status={}; SCALE_FILTERS.status.item=''; @@ -1073,6 +1114,7 @@ function applyScaleFilter(tabKey,reset){ SCALE_FILTERS.status.item=sel?sel.value:''; } } + SCALE_PAGE[tabKey]=1; var body=document.getElementById('scaleSubBody'); if(body)body.innerHTML=renderScaleSubBody(tabKey); } @@ -1167,43 +1209,51 @@ function hideWeightPointTip(){ /* 维度1:设备状态监控 — 状态事件流水 */ SCALE_STATUS_EVENTS=[ - {time:'2026-08-25 08:15:32.456',item:'网络连接',event:'重新连接成功'}, - {time:'2026-08-25 08:00:00.000',item:'运行状态',event:'开餐'}, - {time:'2026-08-25 07:40:12.511',item:'运行状态',event:'加餐'}, - {time:'2026-08-25 06:30:00.000',item:'设备开关机',event:'开机'}, - {time:'2026-08-25 04:12:33.098',item:'运行状态',event:'换餐'}, - {time:'2026-08-24 23:00:00.000',item:'设备开关机',event:'关机'}, - {time:'2026-08-24 22:30:18.764',item:'运行状态',event:'闭餐'}, - {time:'2026-08-24 21:00:02.130',item:'运行状态',event:'进入待机'} + {time:'2026-09-01 21:00:02.130',item:'设备开关机',event:'关机'}, + {time:'2026-09-01 19:30:18.764',item:'运行状态',event:'闭餐'}, + {time:'2026-09-01 17:40:12.511',item:'运行状态',event:'开餐'}, + {time:'2026-09-01 13:20:01.450',item:'运行状态',event:'进入待机'}, + {time:'2026-09-01 13:15:22.310',item:'运行状态',event:'闭餐'}, + {time:'2026-09-01 12:30:00.000',item:'运行状态',event:'换餐'}, + {time:'2026-09-01 10:45:18.674',item:'运行状态',event:'加餐'}, + {time:'2026-09-01 09:10:05.223',item:'运行状态',event:'换餐'}, + {time:'2026-09-01 08:15:32.456',item:'运行状态',event:'加餐'}, + {time:'2026-09-01 07:40:12.511',item:'运行状态',event:'开餐'}, + {time:'2026-09-01 06:30:05.120',item:'网络连接',event:'重新连接成功'}, + {time:'2026-09-01 06:30:00.000',item:'设备开关机',event:'开机'} ]; function renderScaleStatus(){ - const rows=getFilteredScaleRows('status').map(s=>`${s.time}${s.item}${s.event}`).join(''); + var p=getScalePageRows('status'); + const rows=p.rows.map(s=>`${s.time}${s.item}${s.event}`).join(''); return `
设备状态监控
${renderScaleFilterBar('status')} -
${scalePlainThead('status')}${rows}
`; +
${scalePlainThead('status')}${rows}
+ ${renderScalePagination('status',p.total)}`; } -/* 维度2:人脸识别数据 — 开始/结束时间 / 状态 + 视频回放 */ +/* 维度2:视频数据 — 开始/结束时间 + 视频回放 */ var SCALE_FACE_RECORDS=[ - {start:'2026-08-25 08:15:23.456',end:'2026-08-25 08:15:58.210',status:'刷脸+离开',userType:'系统用户',weight:'+486.5g'}, - {start:'2026-08-25 08:14:51.203',end:'2026-08-25 08:15:02.118',status:'刷脸',userType:'系统用户',weight:'+462.0g'}, - {start:'2026-08-25 08:13:47.889',end:'2026-08-25 08:14:10.540',status:'离开',userType:'系统用户',weight:'-445.8g'}, - {start:'2026-08-25 08:12:09.310',end:'2026-08-25 08:12:30.775',status:'刷脸',userType:'陌生人',weight:'+0.0g'} + {start:'2026-09-01 08:26:02.213',end:'2026-09-01 08:26:28.940',status:'离开',userType:'系统用户',weight:'-452.1g'}, + {start:'2026-09-01 08:24:15.556',end:'2026-09-01 08:24:48.771',status:'刷脸+离开',userType:'系统用户',weight:'+495.6g'}, + {start:'2026-09-01 08:21:48.900',end:'2026-09-01 08:22:12.110',status:'刷脸',userType:'系统用户',weight:'+460.8g'}, + {start:'2026-09-01 08:20:05.417',end:'2026-09-01 08:20:30.226',status:'离开',userType:'系统用户',weight:'-478.3g'}, + {start:'2026-09-01 08:18:22.301',end:'2026-09-01 08:18:50.884',status:'刷脸+离开',userType:'系统用户',weight:'+502.0g'}, + {start:'2026-09-01 08:16:40.112',end:'2026-09-01 08:17:05.663',status:'刷脸',userType:'系统用户',weight:'+450.2g'}, + {start:'2026-09-01 08:15:23.456',end:'2026-09-01 08:15:58.210',status:'刷脸+离开',userType:'系统用户',weight:'+486.5g'}, + {start:'2026-09-01 08:14:51.203',end:'2026-09-01 08:15:02.118',status:'刷脸',userType:'系统用户',weight:'+462.0g'}, + {start:'2026-09-01 08:13:47.889',end:'2026-09-01 08:14:10.540',status:'离开',userType:'系统用户',weight:'-445.8g'}, + {start:'2026-09-01 08:12:09.310',end:'2026-09-01 08:12:30.775',status:'刷脸',userType:'陌生人',weight:'+0.0g'} ]; function renderScaleFace(){ - const statusTagMap={ - '刷脸':'刷脸', - '离开':'离开', - '刷脸+离开':'刷脸+离开' - }; - const rows=getFilteredScaleRows('face').map((f)=>{ - const statusTag=statusTagMap[f.status]||''+escapeHtml(f.status)+''; - return `${f.start}${f.end}${statusTag}回放视频`; + var p=getScalePageRows('face'); + const rows=p.rows.map((f)=>{ + return `${f.start}${f.end}回放视频`; }).join(''); - return `
人脸识别数据
+ return `
视频数据
${renderScaleFilterBar('face')} -
${scalePlainThead('face','操作')}${rows}
`; +
${scalePlainThead('face','操作')}${rows}
+ ${renderScalePagination('face',p.total)}`; } /* 录像回放弹窗:自动播放 + 快进/后退 + 进度条跳转 */ @@ -1220,7 +1270,7 @@ function showFaceVideo(start){ mask.id='faceVideoMask'; mask.innerHTML=`
-
人脸识别视频回放 — ${f.start}
+
视频回放 — ${f.start}
@@ -1304,10 +1354,16 @@ function formatFaceVideoTime(t){ /* 维度3:重量变化数据 — 日期/时间 / 用户 / 较上次变化 / 当前余量(含折线图所需字段) */ SCALE_WEIGHT_RECORDS=[ - {start:'2026-08-31 08:15:22.701',end:'2026-08-31 08:15:31.208',target:'EMP0234 · 张伟',userId:'2090646647302909953',delta:'+50.0',total:'486.5',startWeight:'436.5',state:'刷脸'}, - {start:'2026-08-31 08:14:50.512',end:'2026-08-31 08:15:02.118',target:'无用户',userId:'—',delta:'+412.0',total:'462.0',startWeight:'50.0',state:'陌生人'}, - {start:'2026-08-31 08:13:46.098',end:'2026-08-31 08:14:10.540',target:'EMP0357 · 王强',userId:'2090646647302909954',delta:'-62.0',total:'501.2',startWeight:'563.2',state:'离开'}, - {start:'2026-08-31 08:12:08.876',end:'2026-08-31 08:12:30.775',target:'无用户',userId:'—',delta:'0.0',total:'0.0',startWeight:'0.0',state:'重量稳定变化'} + {start:'2026-09-01 08:26:02.213',end:'2026-09-01 08:26:28.940',target:'EMP0421 · 李华',userId:'2090646647302909955',delta:'-452.1',total:'452.1',startWeight:'904.2',state:'离开'}, + {start:'2026-09-01 08:24:15.556',end:'2026-09-01 08:24:48.771',target:'EMP0234 · 张伟',userId:'2090646647302909953',delta:'+495.6',total:'495.6',startWeight:'0.0',state:'陌生人'}, + {start:'2026-09-01 08:21:48.900',end:'2026-09-01 08:22:12.110',target:'EMP0188 · 赵敏',userId:'2090646647302909956',delta:'+460.8',total:'460.8',startWeight:'0.0',state:'刷脸'}, + {start:'2026-09-01 08:20:05.417',end:'2026-09-01 08:20:30.226',target:'EMP0357 · 王强',userId:'2090646647302909954',delta:'-478.3',total:'478.3',startWeight:'956.6',state:'离开'}, + {start:'2026-09-01 08:18:22.301',end:'2026-09-01 08:18:50.884',target:'EMP0234 · 张伟',userId:'2090646647302909953',delta:'+502.0',total:'502.0',startWeight:'0.0',state:'陌生人'}, + {start:'2026-09-01 08:16:40.112',end:'2026-09-01 08:17:05.663',target:'EMP0421 · 李华',userId:'2090646647302909955',delta:'+38.0',total:'450.2',startWeight:'412.2',state:'刷脸'}, + {start:'2026-09-01 08:15:22.701',end:'2026-09-01 08:15:31.208',target:'EMP0234 · 张伟',userId:'2090646647302909953',delta:'+50.0',total:'486.5',startWeight:'436.5',state:'刷脸'}, + {start:'2026-09-01 08:14:50.512',end:'2026-09-01 08:15:02.118',target:'无用户',userId:'—',delta:'+412.0',total:'462.0',startWeight:'50.0',state:'陌生人'}, + {start:'2026-09-01 08:13:46.098',end:'2026-09-01 08:14:10.540',target:'EMP0357 · 王强',userId:'2090646647302909954',delta:'-62.0',total:'501.2',startWeight:'563.2',state:'离开'}, + {start:'2026-09-01 08:12:08.876',end:'2026-09-01 08:12:30.775',target:'无用户',userId:'—',delta:'0.0',total:'0.0',startWeight:'0.0',state:'重量稳定变化'} ]; function renderScaleWeight(){ return `
重量变化数据
@@ -1315,32 +1371,42 @@ function renderScaleWeight(){ ${SCALE_WEIGHT_VIEW==='chart'?renderScaleWeightChart():renderScaleWeightTable()}`; } function renderScaleWeightTable(){ - const rows=getFilteredScaleRows('weight').map(w=>{ + var p=getScalePageRows('weight'); + const rows=p.rows.map(w=>{ const num=parseFloat(w.delta); const color=num>0?'var(--success)':(num<0?'var(--danger)':'var(--text-secondary)'); return `${w.start}${w.target}${w.delta}${w.total}`; }).join(''); - return `
${scalePlainThead('weight')}${rows}
`; + return `
${scalePlainThead('weight')}${rows}
+ ${renderScalePagination('weight',p.total)}`; } /* 维度4:运行日志 — 日期/时间 / 报错类型 / 报错内容(报错代码,20字符) / 操作 */ SCALE_LOG_RECORDS=[ - {time:'2026-08-25 08:10:12.330',type:'异常报错',code:'E1001_WEIGHT_SENSOR_READ_TIMEOUT_RETRY',detail:'E1001_WEIGHT_SENSOR_READ_TIMEOUT_RETRY\n\n[2026-08-25 08:10:12.330] ERROR WeightSensorModule::read()\n 称重传感器读取超时,连续 3 次无响应\n 设备编号: DEV-00025 传感器通道: CH-02\n 已触发自动重试,若重试失败将上报设备故障\n TraceId: 9f3c1a7b-2e4d-4c8a-b1f0-5d6e7f8a9b0c'}, - {time:'2026-08-25 08:02:45.117',type:'性能预警',code:'W2003_RECOG_LATENCY_OVER_THRESHOLD_320MS',detail:'W2003_RECOG_LATENCY_OVER_THRESHOLD_320MS\n\n[2026-08-25 08:02:45.117] WARN RecognitionModule::detect()\n 人脸识别响应延迟 320ms,接近阈值 300ms\n 摄像头: CAM-01 帧率: 25fps\n 建议检查现场光照条件与网络带宽\n TraceId: 4b8e2c31-7a9d-4f5b-9c2e-1a3b4c5d6e7f'}, - {time:'2026-08-25 07:58:03.662',type:'性能预警',code:'W2004_MEMORY_USAGE_HIGH_82PCT',detail:'W2004_MEMORY_USAGE_HIGH_82PCT\n\n[2026-08-25 07:58:03.662] WARN SystemMonitor::check()\n 内存占用 82%,接近预警阈值 85%\n 当前进程: nutrition-scale-app\n 建议关注内存泄漏或及时清理缓存\n TraceId: c5d6e7f8-2a3b-4c4d-8e9f-0a1b2c3d4e5f'}, - {time:'2026-08-25 07:30:00.000',type:'运行日志',code:'I0000_SELF_CHECK_PASS',detail:'I0000_SELF_CHECK_PASS\n\n[2026-08-25 07:30:00.000] INFO SystemMonitor::selfCheck()\n 设备完成夜间自检,各项指标正常\n 传感器: 正常 摄像头: 正常 网络: 正常\n TraceId: 6f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c'} + {time:'2026-09-01 09:15:08.114',type:'运行日志',code:'I1003_CABINET_DOOR_CLOSED',detail:'I1003_CABINET_DOOR_CLOSED\n\n[2026-09-01 09:15:08.114] INFO CabinetModule::close()\n 1号智能货柜柜门已关闭,锁闭正常\n 格口数: 10 已占用: 7\n TraceId: 7a1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d'}, + {time:'2026-09-01 09:05:42.305',type:'异常报错',code:'E1003_CAMERA_FRAME_DROP',detail:'E1003_CAMERA_FRAME_DROP\n\n[2026-09-01 09:05:42.305] ERROR CameraModule::capture()\n 摄像头采集掉帧率超阈值 15%\n 摄像头: CAM-01 当前帧率: 18fps\n 建议检查网络带宽与编码负载\n TraceId: 8b2c3d4e-5f6a-4b7c-9d0e-1f2a3b4c5d6e'}, + {time:'2026-09-01 08:45:10.889',type:'运行日志',code:'I1002_NETWORK_RECONNECTED',detail:'I1002_NETWORK_RECONNECTED\n\n[2026-09-01 08:45:10.889] INFO NetworkModule::reconnect()\n 网络连接重新建立成功\n 服务器: 192.168.1.20 端口: 8443\n TraceId: 9c3d4e5f-6a7b-4c8d-0e1f-2a3b4c5d6e7f'}, + {time:'2026-09-01 08:30:55.671',type:'性能预警',code:'W2005_CPU_USAGE_HIGH_76PCT',detail:'W2005_CPU_USAGE_HIGH_76PCT\n\n[2026-09-01 08:30:55.671] WARN SystemMonitor::check()\n CPU 占用 76%,接近预警阈值 80%\n 当前进程: nutrition-scale-app\n 建议关注并发识别任务量\n TraceId: 0d4e5f6a-7b8c-4d9e-1f2a-3b4c5d6e7f8a'}, + {time:'2026-09-01 08:20:33.410',type:'异常报错',code:'E1002_TEMP_SENSOR_ABNORMAL',detail:'E1002_TEMP_SENSOR_ABNORMAL\n\n[2026-09-01 08:20:33.410] ERROR TempSensorModule::read()\n 冷藏温度传感器读数异常\n 当前温度: 12.8℃ 正常范围: 0~8℃\n 建议检查制冷机组与传感器连接\n TraceId: 1e5f6a7b-8c9d-4e0f-2a3b-4c5d6e7f8a9b'}, + {time:'2026-09-01 08:10:12.330',type:'异常报错',code:'E1001_WEIGHT_SENSOR_READ_TIMEOUT_RETRY',detail:'E1001_WEIGHT_SENSOR_READ_TIMEOUT_RETRY\n\n[2026-09-01 08:10:12.330] ERROR WeightSensorModule::read()\n 称重传感器读取超时,连续 3 次无响应\n 设备编号: DEV-00025 传感器通道: CH-02\n 已触发自动重试,若重试失败将上报设备故障\n TraceId: 9f3c1a7b-2e4d-4c8a-b1f0-5d6e7f8a9b0c'}, + {time:'2026-09-01 08:02:45.117',type:'性能预警',code:'W2003_RECOG_LATENCY_OVER_THRESHOLD_320MS',detail:'W2003_RECOG_LATENCY_OVER_THRESHOLD_320MS\n\n[2026-09-01 08:02:45.117] WARN RecognitionModule::detect()\n 人脸识别响应延迟 320ms,接近阈值 300ms\n 摄像头: CAM-01 帧率: 25fps\n 建议检查现场光照条件与网络带宽\n TraceId: 4b8e2c31-7a9d-4f5b-9c2e-1a3b4c5d6e7f'}, + {time:'2026-09-01 07:58:03.662',type:'性能预警',code:'W2004_MEMORY_USAGE_HIGH_82PCT',detail:'W2004_MEMORY_USAGE_HIGH_82PCT\n\n[2026-09-01 07:58:03.662] WARN SystemMonitor::check()\n 内存占用 82%,接近预警阈值 85%\n 当前进程: nutrition-scale-app\n 建议关注内存泄漏或及时清理缓存\n TraceId: c5d6e7f8-2a3b-4c4d-8e9f-0a1b2c3d4e5f'}, + {time:'2026-09-01 07:30:00.000',type:'运行日志',code:'I0000_SELF_CHECK_PASS',detail:'I0000_SELF_CHECK_PASS\n\n[2026-09-01 07:30:00.000] INFO SystemMonitor::selfCheck()\n 设备完成夜间自检,各项指标正常\n 传感器: 正常 摄像头: 正常 网络: 正常\n TraceId: 6f1a2b3c-4d5e-4f6a-8b7c-9d0e1f2a3b4c'}, + {time:'2026-09-01 07:20:15.220',type:'运行日志',code:'I1001_DEVICE_ONLINE',detail:'I1001_DEVICE_ONLINE\n\n[2026-09-01 07:20:15.220] INFO DeviceModule::startup()\n 餐线营养称设备上线\n 设备编号: DEV-00025 固件版本: v2.4.1\n TraceId: 2f3a4b5c-6d7e-4f8a-9b0c-1d2e3f4a5b6c'} ]; function truncateCode(code){ if(!code)return ''; return code.length>20?code.slice(0,20)+'…':code; } function renderScaleLog(){ - const rows=getFilteredScaleRows('log').map(l=>{ + var p=getScalePageRows('log'); + const rows=p.rows.map(l=>{ const codeHtml=`${escapeHtml(truncateCode(l.code))}`; return `${l.time}${l.type}${codeHtml}查看详情`; }).join(''); return `
运行日志
-
${scaleThead('log','操作')}${rows}
`; +
${scaleThead('log','操作')}${rows}
+ ${renderScalePagination('log',p.total)}`; } function showLogDetail(code){ var rec=SCALE_LOG_RECORDS.filter(function(l){return l.code===code;})[0]; diff --git a/web-admin/nutrition/doc/CHANGELOG.md b/web-admin/nutrition/doc/CHANGELOG.md index 4596de0..5e626f7 100644 --- a/web-admin/nutrition/doc/CHANGELOG.md +++ b/web-admin/nutrition/doc/CHANGELOG.md @@ -1,5 +1,13 @@ # 营养用餐管理端 CHANGELOG +## [2026-09-01] feat: 餐线营养秤四Tab分页 + 日期默认当天 + 人脸识别数据更名视频数据 + +- `din-terminal.html` 设备概览「餐线营养秤」: + - 「人脸识别数据」Tab 更名为「视频数据」,并去掉该 Tab 下「状态」列 + - 四个 Tab(设备状态监控/重量变化数据/视频数据/运行日志)表格新增分页(每页 5 条,共 N 条/上一页/页码/下一页),重量变化数据的折线图视图不分页 + - 日期筛选栏默认当天(动态取浏览器当前日期),「重置」回到当天 + - 四个 Tab mock 数据日期统一为当天并扩充条数(状态监控 12 条、其余各 10 条) + ## [2026-09-01] feat: 净菜订单生成历史加建议熟重/规格列 + 食谱快速创建份数改规格 - `prod-clean-order.html` 净菜订单: