// 统一列表组件:setListPager 搜索 + 分页 + 排序(_lpSort) // ================== 通用列表:搜索 + 分页 + 排序 ================== // 用法: // setListPager(key,{data:()=>array, filter:(item,kw)=>bool, render:(item)=>html, // tbody:'tb-id', pager:'pager-id', pageSize:N, // sortValue:(item,colKey)=>值, // 可排序列的取值函数 // empty:'...'}); // applyListPager(key); // 数据变化后重渲染(含搜索/翻页/排序状态) // initListSearch(key,'search-id'); // 搜索框绑定 // _lpSort(key,'colKey'); // 表头排序:th 加 data-sort="colKey" + onclick, // // 再点切换升降序,第三次取消;排序指示器自动更新 var _LIST_PAGERS={}; function _lp(key){ return _LIST_PAGERS[key] || (_LIST_PAGERS[key]={page:1,kw:'',cfg:null,sort:null}); } function setListPager(key,cfg){ // 只更新配置,不重置 page/kw/sort —— 监控列表 5 秒自动刷新时保持用户当前状态 var st=_lp(key); st.cfg=cfg; } function initListSearch(key,inputId){ var input=document.getElementById(inputId); if(!input||input.dataset.bound)return; input.dataset.bound='1'; input.addEventListener('input',function(){ var st=_lp(key); st.kw=this.value.trim(); st.page=1; applyListPager(key); }); } function _lpSort(key,colKey){ var st=_lp(key); if(st.sort&&st.sort.key===colKey){ if(st.sort.dir===1)st.sort.dir=-1; // 升序 → 降序 else if(st.sort.dir===-1)st.sort=null; // 降序 → 取消排序 else st.sort={key:colKey,dir:1}; }else{ st.sort={key:colKey,dir:1}; } applyListPager(key); } function applyListPager(key){ var st=_lp(key); if(!st.cfg)return; var cfg=st.cfg; var all=(cfg.data&&cfg.data())||[]; var kw=st.kw.toLowerCase(); var filtered=kw?all.filter(function(x){return cfg.filter(x,kw);}):all; // 排序:cfg.sortValue 取列值;空值/缺失恒排最后;字符串用中文数字感知比较(10 排在 9 后) if(st.sort&&cfg.sortValue){ var sk=st.sort.key, dir=st.sort.dir; filtered=filtered.slice().sort(function(a,b){ var va=cfg.sortValue(a,sk), vb=cfg.sortValue(b,sk); if(va===vb)return 0; if(va==null||va==='')return 1; if(vb==null||vb==='')return -1; if(typeof va==='number'&&typeof vb==='number')return (va-vb)*dir; return String(va).localeCompare(String(vb),'zh-Hans-CN',{numeric:true})*dir; }); } var pageSize=cfg.pageSize||10; var pages=Math.max(1,Math.ceil(filtered.length/pageSize)); if(st.page>pages)st.page=pages; if(st.page<1)st.page=1; var start=(st.page-1)*pageSize; var slice=filtered.slice(start,start+pageSize); var tb=document.getElementById(cfg.tbody); if(tb){ tb.innerHTML=slice.map(cfg.render).join('')||(cfg.empty||'无数据'); // 表头排序指示器(th[data-sort],所有表格统一) if(cfg.sortValue){ var table=tb.closest('table'); if(table)table.querySelectorAll('thead th[data-sort]').forEach(function(th){ th.classList.add('sortable'); th.classList.toggle('sort-asc',!!st.sort&&st.sort.key===th.dataset.sort&&st.sort.dir===1); th.classList.toggle('sort-desc',!!st.sort&&st.sort.key===th.dataset.sort&&st.sort.dir===-1); }); } } var pg=document.getElementById(cfg.pager); if(pg)pg.innerHTML=_lpPagerHtml(key,pages,st.page,filtered.length,pageSize); } function _lpPagerHtml(key,pages,cur,total,pageSize){ if(pages<=1)return total>0?'
共 '+total+' 条
':''; var h='
共 '+total+' 条'; h+=''; for(var p=Math.max(1,cur-2);p<=Math.min(pages,cur+2);p++){ h+=''; } h+=''; h+='
'; return h; } function _lpGo(key,p){ var st=_lp(key); st.page=p; applyListPager(key); }