feat: 餐线营养秤四Tab分页 + 日期默认当天 + 人脸识别数据更名视频数据
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
2996e835c7
commit
deb366e19c
@@ -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='<div class="ov-daily-pagination"><span class="ov-daily-pagination__total">共 '+total+' 条</span>';
|
||||
html+='<button class="page-btn" onclick="goScalePage(\''+tabKey+'\','+(page-1)+')"'+(page<=1?' disabled style="opacity:.4;cursor:not-allowed"':'')+'>‹</button>';
|
||||
for(var i=1;i<=totalPages;i++){
|
||||
html+='<button class="page-btn'+(i===page?' active':'')+'" onclick="goScalePage(\''+tabKey+'\','+i+')">'+i+'</button>';
|
||||
}
|
||||
html+='<button class="page-btn" onclick="goScalePage(\''+tabKey+'\','+(page+1)+')"'+(page>=totalPages?' disabled style="opacity:.4;cursor:not-allowed"':'')+'>›</button></div>';
|
||||
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=>`<tr><td>${s.time}</td><td>${s.item}</td><td>${s.event}</td></tr>`).join('');
|
||||
var p=getScalePageRows('status');
|
||||
const rows=p.rows.map(s=>`<tr><td>${s.time}</td><td>${s.item}</td><td>${s.event}</td></tr>`).join('');
|
||||
return `<div class="ov-section-title">设备状态监控</div>
|
||||
${renderScaleFilterBar('status')}
|
||||
<div style="overflow-x:auto"><table class="ov-daily-table">${scalePlainThead('status')}<tbody>${rows}</tbody></table></div>`;
|
||||
<div style="overflow-x:auto"><table class="ov-daily-table">${scalePlainThead('status')}<tbody>${rows}</tbody></table></div>
|
||||
${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={
|
||||
'刷脸':'<span class="tag tag-blue">刷脸</span>',
|
||||
'离开':'<span class="tag tag-gray">离开</span>',
|
||||
'刷脸+离开':'<span class="tag tag-purple">刷脸+离开</span>'
|
||||
};
|
||||
const rows=getFilteredScaleRows('face').map((f)=>{
|
||||
const statusTag=statusTagMap[f.status]||'<span class="tag tag-gray">'+escapeHtml(f.status)+'</span>';
|
||||
return `<tr><td>${f.start}</td><td>${f.end}</td><td>${statusTag}</td><td><a class="link" onclick="showFaceVideo('${f.start}')">回放视频</a></td></tr>`;
|
||||
var p=getScalePageRows('face');
|
||||
const rows=p.rows.map((f)=>{
|
||||
return `<tr><td>${f.start}</td><td>${f.end}</td><td><a class="link" onclick="showFaceVideo('${f.start}')">回放视频</a></td></tr>`;
|
||||
}).join('');
|
||||
return `<div class="ov-section-title">人脸识别数据</div>
|
||||
return `<div class="ov-section-title">视频数据</div>
|
||||
${renderScaleFilterBar('face')}
|
||||
<div style="overflow-x:auto"><table class="ov-daily-table">${scalePlainThead('face','操作')}<tbody>${rows}</tbody></table></div>`;
|
||||
<div style="overflow-x:auto"><table class="ov-daily-table">${scalePlainThead('face','操作')}<tbody>${rows}</tbody></table></div>
|
||||
${renderScalePagination('face',p.total)}`;
|
||||
}
|
||||
|
||||
/* 录像回放弹窗:自动播放 + 快进/后退 + 进度条跳转 */
|
||||
@@ -1220,7 +1270,7 @@ function showFaceVideo(start){
|
||||
mask.id='faceVideoMask';
|
||||
mask.innerHTML=`<div class="face-video-modal">
|
||||
<div class="face-video-modal__header">
|
||||
<div class="face-video-modal__title">人脸识别视频回放 — ${f.start}</div>
|
||||
<div class="face-video-modal__title">视频回放 — ${f.start}</div>
|
||||
<button class="face-video-modal__close" onclick="closeFaceVideo()">×</button>
|
||||
</div>
|
||||
<div class="face-video-modal__body">
|
||||
@@ -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 `<div class="ov-section-title">重量变化数据</div>
|
||||
@@ -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 `<tr><td>${w.start}</td><td>${w.target}</td><td><span style="color:${color}">${w.delta}</span></td><td>${w.total}</td></tr>`;
|
||||
}).join('');
|
||||
return `<div style="overflow-x:auto"><table class="ov-daily-table">${scalePlainThead('weight')}<tbody>${rows}</tbody></table></div>`;
|
||||
return `<div style="overflow-x:auto"><table class="ov-daily-table">${scalePlainThead('weight')}<tbody>${rows}</tbody></table></div>
|
||||
${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=`<span title="${escapeAttr(l.code)}">${escapeHtml(truncateCode(l.code))}</span>`;
|
||||
return `<tr><td>${l.time}</td><td>${l.type}</td><td>${codeHtml}</td><td><a class="link" onclick="showLogDetail('${escapeAttr(l.code)}')">查看详情</a></td></tr>`;
|
||||
}).join('');
|
||||
return `<div class="ov-section-title">运行日志</div>
|
||||
<div style="overflow-x:auto"><table class="ov-daily-table">${scaleThead('log','操作')}<tbody>${rows}</tbody></table></div>`;
|
||||
<div style="overflow-x:auto"><table class="ov-daily-table">${scaleThead('log','操作')}<tbody>${rows}</tbody></table></div>
|
||||
${renderScalePagination('log',p.total)}`;
|
||||
}
|
||||
function showLogDetail(code){
|
||||
var rec=SCALE_LOG_RECORDS.filter(function(l){return l.code===code;})[0];
|
||||
|
||||
@@ -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` 净菜订单:
|
||||
|
||||
Reference in New Issue
Block a user