🔥 消防市场准入及证书模压台账管理系统

📊 超期统计

0
1个月内
超期/待检验
0
3个月内
超期/待检验
0
6个月内
超期/待检验
0
12个月内
超期/待检验
0
记录总数
每页:
'; const blob=new Blob(['\ufeff'+html],{type:'application/vnd.ms-excel;charset=utf-8'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=`台账导出_${TABS_DEF.find(t=>t.id===currentTab)?.label}_${new Date().toLocaleDateString('zh-CN').replace(/\//g,'')}.xls`; a.click(); toast('导出完成','success'); } // ============================================================ // 超期统计面板 // ============================================================ function renderStats(){ const now = new Date(); [1,3,6,12].forEach(m=>{ const deadline = new Date(now.getFullYear(), now.getMonth()-m, now.getDate()); let count = 0; allData.forEach(rec=>{ const ins = getInspectStatus(rec); if(ins.status==='overdue' || ins.status==='warning'){ const baseStr = rec['上次合格报告时间']||rec['报告签发日期']||''; const baseDate = parseDate(baseStr); if(baseDate && baseDate <= deadline) count++; } }); const el = document.getElementById('stat-'+m+'m'); if(el) el.textContent = count; }); const totalEl = document.getElementById('stat-total'); if(totalEl) totalEl.textContent = allData.length; } function showOverdueDetail(months){ const now = new Date(); const deadline = new Date(now.getFullYear(), now.getMonth()-months, now.getDate()); const records = []; allData.forEach((rec,idx)=>{ const ins = getInspectStatus(rec); if(ins.status==='overdue' || ins.status==='warning'){ const baseStr = rec['上次合格报告时间']||rec['报告签发日期']||''; const baseDate = parseDate(baseStr); if(baseDate && baseDate <= deadline){ records.push({rec, idx, ins, baseDate, months: monthsDiff(baseDate, now)}); } } }); // 按超期月数排序 records.sort((a,b)=>b.months-a.months); document.getElementById('overdue-title').childNodes[0].nodeValue = `📊 ${months}个月内超期/待检验明细(共${records.length}条) `; if(!records.length){ document.getElementById('overdue-body').innerHTML = '
暂无数据
'; showModal('modal-overdue'); return; } let html = ''; html += ''; records.forEach((r,i)=>{ const rec = r.rec; const baseStr = rec['上次合格报告时间']||rec['报告签发日期']||''; const rowBg = r.ins.status==='overdue' ? 'background:#fff1f0' : 'background:#fffbe6'; const stag = r.ins.status==='overdue' ? ''+r.ins.label+'' : ''+r.ins.label+''; html += ``; }); html += '
#管理编号产品型号/名称认证类型基准日期已过(月)状态操作
${i+1}${escHtml(rec['管理编号']||'')}${escHtml(rec['产品型号/名称']||'')}${escHtml(rec['认证类型']||'')}${escHtml(baseStr)}${r.months}${stag}
'; document.getElementById('overdue-body').innerHTML = html; showModal('modal-overdue'); } // ============================================================ // ============================================================ // 字段显示切换 + 拖拽排序 // ============================================================ function toggleAllCols(){ openSettings(); } function renderFieldList(){ const fl=document.getElementById('field-list'); if(!fl) return; fl.innerHTML=FIELD_DEFS.map((f,idx)=>{ const isSpecial = f.key==='__action__' || f.key==='__status__'; const label = isSpecial ? (f.label||f.key) : f.key; const shown=!CFG.hiddenFields.has(f.key); // 特殊列不能隐藏,显示特殊样式 if(isSpecial){ return `
${label}
`; } return `
${label}
`; }).join(''); // 拖拽事件 fl.querySelectorAll('.field-chip').forEach(chip=>{ chip.addEventListener('dragstart', function(e){ e.dataTransfer.setData('text/plain', this.dataset.idx); this.style.opacity='0.4'; }); chip.addEventListener('dragend', function(){ this.style.opacity='1'; fl.querySelectorAll('.field-chip').forEach(c=>c.style.borderLeft=''); }); chip.addEventListener('dragover', function(e){ e.preventDefault(); fl.querySelectorAll('.field-chip').forEach(c=>c.style.borderLeft=''); this.style.borderLeft='3px solid #1677ff'; }); chip.addEventListener('dragleave', function(){ this.style.borderLeft=''; }); chip.addEventListener('drop', function(e){ e.preventDefault(); this.style.borderLeft=''; const fromIdx=parseInt(e.dataTransfer.getData('text/plain')); const toIdx=parseInt(this.dataset.idx); if(fromIdx!==toIdx){ const item=FIELD_DEFS.splice(fromIdx,1)[0]; FIELD_DEFS.splice(toIdx,0,item); renderFieldList(); } }); }); } function moveField(idx, dir){ const newIdx=idx+dir; if(newIdx<0||newIdx>=FIELD_DEFS.length) return; const item=FIELD_DEFS.splice(idx,1)[0]; FIELD_DEFS.splice(newIdx,0,item); renderFieldList(); } function toggleField(key,chip){ if(CFG.hiddenFields.has(key)){ CFG.hiddenFields.delete(key); chip.classList.add('shown'); } else { CFG.hiddenFields.add(key); chip.classList.remove('shown'); } } // ============================================================ // 设置 // ============================================================ function openSettings(){ document.getElementById('s-normal-warn').value=CFG.normalWarn; document.getElementById('s-normal-expire').value=CFG.normalExpire; document.getElementById('s-fb-warn').value=CFG.fbWarn; document.getElementById('s-fb-expire').value=CFG.fbExpire; document.getElementById('s-page-size').value=CFG.pageSize; renderFieldList(); showModal('modal-settings'); } function saveSettings(){ CFG.normalWarn=parseInt(document.getElementById('s-normal-warn').value)||22; CFG.normalExpire=parseInt(document.getElementById('s-normal-expire').value)||24; CFG.fbWarn=parseInt(document.getElementById('s-fb-warn').value)||9; CFG.fbExpire=parseInt(document.getElementById('s-fb-expire').value)||12; CFG.pageSize=parseInt(document.getElementById('s-page-size').value)||100; document.getElementById('page-size-sel').value=CFG.pageSize; saveCfg(); closeModal('modal-settings'); renderTable(); toast('设置已保存','success'); } function changePageSize(){ CFG.pageSize=parseInt(document.getElementById('page-size-sel').value)||100; currentPage=1; saveCfg(); renderTable(); } // 重置所有数据到初始状态 function resetAllData(){ if(!confirm('⚠️ 确定要重置为初始数据吗?\n\n这将清除所有新增、删除、修改的记录,不可恢复!')) return; if(!confirm('再次确认:重置后数据将恢复为导入时的原始状态,请确认!')) return; localStorage.removeItem('tadata'); allData = RAW_RECORDS.map((r,i)=>({...r,_id:i+1})); migrateFieldNames(); saveData(); closeModal('modal-settings'); currentPage=1; renderTabs(); renderTable(); toast('数据已重置为初始状态','success'); } // ============================================================ // 弹窗通用 // ============================================================ function showModal(id){document.getElementById(id).classList.add('show');} function closeModal(id){document.getElementById(id).classList.remove('show');} document.addEventListener('click',function(e){ if(e.target.classList.contains('modal-mask')) e.target.classList.remove('show'); }); // ============================================================ // 通知 // ============================================================ function toast(msg,type=''){ const wrap=document.getElementById('toast'); const el=document.createElement('div'); el.className='toast-item '+(type||''); el.textContent=msg; wrap.appendChild(el); setTimeout(()=>el.remove(),3000); } // ============================================================ // 工具 // ============================================================ function escHtml(s){ return String(s).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } // ============================================================ // 加载SheetJS (用于xlsx导入) // ============================================================ (function loadSheetJS(){ const s=document.createElement('script'); s.src='https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js'; s.onerror=()=>{}; document.head.appendChild(s); })(); // 启动 init();