'+
+ html+='
关联货柜:'+agg.ctNo+' 客户:'+agg.cust+' 渠道:'+agg.channel+' 业务月份:'+agg.month+'
'+
'
收入明细
费用项 金额 '+incRows+'小计 '+fmt(iSum)+'
'+
'
成本明细
费用项 金额 '+cosRows+'小计 '+fmt(cSum)+'
'+
'
';
} else {
- const rows=profitTicketData.filter(x=>({customer:x.cust,container:x.ctNo,month:x.month}[dim]===val));
+ const rows=agg.tickets||profitVisibleTickets.filter(x=>({customer:x.cust,container:x.ctNo,month:x.month}[dim]===val));
if(!rows.length){
html+='
该'+label+'下暂无明细单据
';
} else {
@@ -15650,10 +16373,10 @@ function openProfitDetail(dim,val){
const rate=profitRate(t.profit,t.income);
const rc=rate>=0?'#52c41a':'#f5222d';
sI+=t.income;sC+=t.cost;sP+=t.profit;
- rb+='
'+t.ticket+' '+t.cust+' '+t.channel+' '+t.ctNo+' '+fmt(t.income)+' '+fmt(t.cost)+' '+fmt(t.profit)+' '+(rate*100).toFixed(1)+'% ';
+ rb+='
'+t.ticket+' '+t.cust+' '+t.channel+' '+t.ctNo+' '+fmt(t.income)+' '+fmt(t.cost)+' '+fmt(t.profit)+' '+rate.toFixed(1)+'% ';
});
const tRate=profitRate(sP,sI);
- rb+='
本页合计('+rows.length+' 单) '+fmt(sI)+' '+fmt(sC)+' '+fmt(sP)+' '+(tRate*100).toFixed(1)+'% ';
+ rb+='
本页合计('+rows.length+' 单) '+fmt(sI)+' '+fmt(sC)+' '+fmt(sP)+' '+tRate.toFixed(1)+'% ';
html+='
关联单票明细('+rows.length+' 单)
单票号 客户 渠道 货柜号 收入 成本 利润 利润率 '+rb+'
';
}
}
@@ -15840,6 +16563,21 @@ function deleteVehicle(key,id){
}
// ==================== NAVIGATION ====================
+function toggleTopMessageMenu(event){
+ if(event)event.stopPropagation();
+ const menu=document.getElementById('topMessageMenu');
+ if(menu)menu.classList.toggle('open');
+}
+function openTopMessagePage(page,event){
+ if(event)event.stopPropagation();
+ const menu=document.getElementById('topMessageMenu');
+ if(menu)menu.classList.remove('open');
+ switchPage(page);
+}
+document.addEventListener('click',function(event){
+ const menu=document.getElementById('topMessageMenu');
+ if(menu&&!menu.contains(event.target))menu.classList.remove('open');
+});
let currentPage='dashboard';
function switchPage(page,el){
document.querySelectorAll('.page').forEach(p=>p.classList.remove('active'));
@@ -16380,6 +17118,76 @@ hideModal('modal-package-edit');
renderPackage();
}
+// ==================== 全局表格与查询区规范化 ====================
+let _unifiedTableFrame=0;
+
+function tableDirectCells(row){
+ return Array.from(row.children).filter(function(cell){return cell.tagName==='TH'||cell.tagName==='TD';});
+}
+
+function normalizeTableOperationColumn(table){
+ if(!table||!table.tHead)return;
+ const headerRows=Array.from(table.tHead.rows);
+ const headerRow=headerRows.find(function(row){
+ return tableDirectCells(row).some(function(cell){return cell.textContent.replace(/[\s↑↓↕]/g,'')==='操作';});
+ });
+ if(!headerRow)return;
+ const headerCells=tableDirectCells(headerRow);
+ const operationHeader=headerCells.find(function(cell){return cell.textContent.replace(/[\s↑↓↕]/g,'')==='操作';});
+ if(!operationHeader)return;
+ let sourceIndex=Number(table.dataset.operationSourceIndex);
+ if(!Number.isInteger(sourceIndex)||sourceIndex<0){
+ sourceIndex=headerCells.indexOf(operationHeader);
+ table.dataset.operationSourceIndex=String(sourceIndex);
+ }
+ const firstHeader=headerCells[0];
+ const hasSelectionFirst=!!(firstHeader&&(firstHeader.querySelector('input[type="checkbox"],input[type="radio"]')||firstHeader.textContent.trim()===''));
+ const keepOperationAtEnd=!!table.closest('#page-tenant-list,#page-warehouse-tier-fee');
+ const targetIndex=keepOperationAtEnd?headerCells.length-1:(hasSelectionFirst?1:0);
+ operationHeader.classList.add('unified-operation-col');
+ operationHeader.dataset.operationColumn='1';
+ let currentHeaderCells=tableDirectCells(headerRow);
+ if(currentHeaderCells.indexOf(operationHeader)!==targetIndex){
+ headerRow.insertBefore(operationHeader,currentHeaderCells[targetIndex]||null);
+ }
+ const expectedCount=headerCells.length;
+ Array.from(table.tBodies).forEach(function(tbody){
+ Array.from(tbody.rows).forEach(function(row){
+ let cells=tableDirectCells(row);
+ if(cells.length!==expectedCount)return;
+ let operationCell=cells.find(function(cell){return cell.dataset.operationColumn==='1';});
+ if(!operationCell)operationCell=cells[sourceIndex];
+ if(!operationCell)return;
+ operationCell.dataset.operationColumn='1';
+ operationCell.classList.add('unified-operation-col');
+ cells=tableDirectCells(row);
+ if(cells.indexOf(operationCell)!==targetIndex)row.insertBefore(operationCell,cells[targetIndex]||null);
+ });
+ });
+ table.classList.add('unified-data-table');
+}
+
+function normalizeAllListPresentation(){
+ document.querySelectorAll('.page table').forEach(normalizeTableOperationColumn);
+ document.querySelectorAll('.page .search-row,.page .inbound-search-section,.page #rsq-wrap,.page .ds-search').forEach(function(panel){panel.classList.add('unified-search-panel');});
+}
+
+function scheduleListPresentationNormalize(){
+ if(_unifiedTableFrame)return;
+ _unifiedTableFrame=requestAnimationFrame(function(){
+ _unifiedTableFrame=0;
+ normalizeAllListPresentation();
+ });
+}
+
+function initUnifiedListPresentation(){
+ normalizeAllListPresentation();
+ const observer=new MutationObserver(function(mutations){
+ if(mutations.some(function(m){return m.type==='childList'&&m.addedNodes.length;}))scheduleListPresentationNormalize();
+ });
+ observer.observe(document.body,{childList:true,subtree:true});
+}
+
// ==================== INIT ====================
document.addEventListener('DOMContentLoaded',()=>{
initCharts();
@@ -16448,6 +17256,7 @@ renderCost();
renderUsers();
renderRoles();
renderSysTenant();
+initUnifiedListPresentation();
});
// ==================== BRAND SETTINGS ====================
@@ -16528,6 +17337,7 @@ function toggleContainerFields(){
// ==================== DASHBOARD FULLSCREEN ====================
let _fsChartTimer=null;
+let _fsResizeTimer=null;
function toggleDashboardFullscreen(){
const isFs=document.body.classList.contains('dashboard-fullscreen');
if(!isFs){
@@ -16541,6 +17351,7 @@ if(!isFs){
// Start clock
updateFsClock();
_fsChartTimer=setInterval(updateFsClock,1000);
+ refreshDashboardData(false);
// Update btn text
const btn=document.getElementById('dashboardFullscreenBtn');
if(btn){btn.textContent='⛶ 退出全屏';btn.title='退出全屏模式';}
@@ -16555,6 +17366,7 @@ document.body.classList.remove('dashboard-fullscreen');
if(document.exitFullscreen&&document.fullscreenElement)document.exitFullscreen().catch(()=>{});
else if(document.webkitExitFullscreen&&document.webkitFullscreenElement)document.webkitExitFullscreen();
if(_fsChartTimer){clearInterval(_fsChartTimer);_fsChartTimer=null;}
+scheduleDashboardResize();
const btn=document.getElementById('dashboardFullscreenBtn');
if(btn){btn.textContent='⛶ 数据看板全屏';btn.title='首页看板全屏';}
}
@@ -16562,9 +17374,33 @@ if(btn){btn.textContent='⛶ 数据看板全屏';btn.title='首页看板全屏';
function updateFsClock(){
const d=new Date();
const pad=n=>String(n).padStart(2,'0');
-const timeStr=`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
-const el=document.getElementById('fsClock');
-if(el)el.textContent=timeStr;
+const dateEl=document.getElementById('fsDate');
+const timeEl=document.getElementById('fsClock');
+if(dateEl)dateEl.textContent=`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
+if(timeEl)timeEl.textContent=`${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
+}
+
+function scheduleDashboardResize(){
+if(_fsResizeTimer)clearTimeout(_fsResizeTimer);
+_fsResizeTimer=setTimeout(()=>{
+ window.dispatchEvent(new Event('resize'));
+ if(window.Chart&&Chart.instances){
+ Object.keys(Chart.instances).forEach(key=>{const chart=Chart.instances[key];if(chart&&chart.resize)chart.resize();});
+ }
+ _fsResizeTimer=null;
+},220);
+}
+
+function refreshDashboardData(showFeedback=true){
+const d=new Date();
+const pad=n=>String(n).padStart(2,'0');
+const stamp=`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
+const updated=document.getElementById('dashboardUpdatedAt');
+const fsUpdated=document.getElementById('fsUpdatedAt');
+if(updated)updated.textContent=stamp;
+if(fsUpdated)fsUpdated.textContent=stamp;
+scheduleDashboardResize();
+if(showFeedback)showToast('数据看板已刷新','success');
}
// ==================== 入库单列表 - 合关报关 ====================
@@ -17126,7 +17962,7 @@ var tb=document.getElementById('tbody-arap');
if(!tb)return;
var auditCls={'财务通过':'color:#52c41a;background:#f6ffed;border:1px solid #b7eb8f;padding:2px 10px;border-radius:10px;font-size:12px','客服提交':'color:#1890ff;background:#e6f7ff;border:1px solid #91d5ff;padding:2px 10px;border-radius:10px;font-size:12px','新增':'color:#fa8c16;background:#fff7e6;border:1px solid #ffd591;padding:2px 10px;border-radius:10px;font-size:12px'};
tb.innerHTML=arapData.map(function(d,i){
-var ops='
详情 '
+var ops='
详情 '
+'
审核 '
+'
编辑 '
+'
禁止结算 '
@@ -17149,6 +17985,63 @@ return '
'+item[0]+' '+item[1]+' ';}).join('');
+
+ var steps=[{name:'费用已生成',done:true,desc:'业务单据触发费用生成'},{name:'客服已提交',done:d.auditStatus!=='新增',desc:d.auditStatus==='新增'?'等待客服确认':'费用信息已提交财务'},{name:'财务已审核',done:d.auditStatus==='财务通过',desc:d.auditStatus==='财务通过'?'审核通过,可参与对账':'等待财务审核'}];
+ document.getElementById('arap-detail-timeline').innerHTML=steps.map(function(step,i){return ''+(step.done?'✓':'·')+' '+(i
':'')+''+step.name+' '+step.desc+'
';}).join('');
+
+ document.getElementById('tbody-arap-detail-business').innerHTML=''+(d.whCode||'—')+' '+(d.orderStatus||'—')+' '+(d.dispatchNo||'—')+' '+(d.containerNo||'—')+' '+(d.cabinetNo||'—')+' '+(d.billNo||'暂未生成')+' ';
+ var baseDay=String(10+currentArapDetailIndex).padStart(2,'0');
+ var logs=[{time:'2026-07-'+baseDay+' 09:20',node:'生成费用',operator:'系统',result:'成功',remark:'由业务单据自动生成'}];
+ if(d.auditStatus!=='新增')logs.push({time:'2026-07-'+baseDay+' 10:05',node:'客服提交',operator:'客服专员',result:'已提交',remark:'费用信息核对完成'});
+ if(d.auditStatus==='财务通过')logs.push({time:'2026-07-'+baseDay+' 14:30',node:'财务审核',operator:'财务专员',result:'审核通过',remark:'允许参与结算'});
+ document.getElementById('tbody-arap-detail-log').innerHTML=logs.map(function(log){return '
'+log.time+' '+log.node+' '+log.operator+' '+log.result+' '+log.remark+' ';}).join('');
+}
+
// ============ 客户对账单 ============
var customerReconStmtData=[
{id:'Y2607095',status:'待审核',customer:'杭州恺予科技有限公司',startDate:'2026-07-21',endDate:'2026-08-20',period:7,currency:'CNY',rate:6.8,totalAr:86809.8,paidAr:0,lastPayTime:'',settled:'否',invoiceDate:'',remark:'',creator:'叶珊珊',createDate:'2026-07-21 14:14:22',updater:'叶珊珊',updateDate:'2026-07-21 14:14:22'},
@@ -17386,6 +18279,8 @@ function renderSettlementAr(){
totalAr+=d.arAmount;totalRec+=d.received;totalBal+=d.balance;
return '
'+
' '+
+ '详情 '+
+ (d.balance>0&&d.status==='生效'?'部分收款 ':'')+' '+
''+d.id+' '+
''+d.customer+' '+
''+d.feeType+' '+
@@ -17402,7 +18297,6 @@ function renderSettlementAr(){
''+d.creator+' '+
''+(d.reviewer||'-')+' '+
''+d.status+' '+
- '详情 编辑 '+
' ';
}).filter(Boolean);
tb.innerHTML=rows.length?rows.join(''):'
暂无匹配数据 ';
@@ -17418,10 +18312,208 @@ function resetSettlementAr(){
renderSettlementAr();
}
// ============ 结算单应付 ============
+var settlementApData=[
+ {id:'SAP-202606-001',supplier:'中远海运集装箱运输有限公司',feeType:'海运费',currency:'CNY',apAmount:168000,paid:100000,balance:68000,billNo:'SUP-RECON-202606-001',period:'2026-06',genDate:'2026-06-25',dueDate:'2026-07-25',payStatus:'部分付款',approveStatus:'已审批',hasProfit:'是',profitAmount:12600,creator:'苏天雅',reviewer:'王建国',status:'生效'},
+ {id:'SAP-202606-002',supplier:'马士基(中国)航运有限公司',feeType:'订舱费',currency:'USD',apAmount:28600,paid:0,balance:28600,billNo:'SUP-RECON-202606-002',period:'2026-06',genDate:'2026-06-28',dueDate:'2026-07-28',payStatus:'待付款',approveStatus:'已审批',hasProfit:'否',profitAmount:0,creator:'苏天雅',reviewer:'王建国',status:'生效'},
+ {id:'SAP-202607-001',supplier:'宁波中基惠通报关有限公司',feeType:'报关费',currency:'CNY',apAmount:42600,paid:42600,balance:0,billNo:'SUP-RECON-202607-001',period:'2026-07',genDate:'2026-07-05',dueDate:'2026-08-05',payStatus:'已结清',approveStatus:'已审批',hasProfit:'否',profitAmount:0,creator:'李明',reviewer:'王建国',status:'生效'},
+ {id:'SAP-202607-002',supplier:'宁波北仑顺达集装箱运输',feeType:'拖车费',currency:'CNY',apAmount:93500,paid:35000,balance:58500,billNo:'SUP-RECON-202607-002',period:'2026-07',genDate:'2026-07-12',dueDate:'2026-08-12',payStatus:'部分付款',approveStatus:'已审批',hasProfit:'是',profitAmount:6800,creator:'李芳',reviewer:'王建国',status:'生效'},
+ {id:'SAP-202607-003',supplier:'华测检测认证集团',feeType:'认证费',currency:'CNY',apAmount:31800,paid:0,balance:31800,billNo:'SUP-RECON-202607-003',period:'2026-07',genDate:'2026-07-18',dueDate:'2026-08-18',payStatus:'待付款',approveStatus:'审批中',hasProfit:'否',profitAmount:0,creator:'苏天雅',reviewer:'',status:'待审批'}
+];
+
function renderSettleAp(){
-var tb=document.getElementById('tbody-settle-ap');
-if(!tb)return;
-tb.innerHTML='
暂无数据 ';
+ var tb=document.getElementById('tbody-settle-ap');
+ if(!tb)return;
+ var status=document.getElementById('sap-status')?document.getElementById('sap-status').value:'全部状态';
+ var supplier=document.getElementById('sap-supplier')?document.getElementById('sap-supplier').value:'全部供应商';
+ var currency=document.getElementById('sap-currency')?document.getElementById('sap-currency').value:'全部币种';
+ var no=(document.getElementById('sap-no')?document.getElementById('sap-no').value:'').trim().toLowerCase();
+ var payCls={'已结清':'tag-green','部分付款':'tag-orange','待付款':'tag-red'};
+ var approveCls={'已审批':'tag-green','审批中':'tag-orange','草稿':'tag-gray'};
+ var statusCls={'生效':'tag-green','待审批':'tag-orange','草稿':'tag-gray'};
+ var total=0,paid=0,balance=0,profit=0;
+ var rows=settlementApData.map(function(d){
+ if(status!=='全部状态'&&d.payStatus!==status)return null;
+ if(supplier!=='全部供应商'&&d.supplier!==supplier)return null;
+ if(currency!=='全部币种'&&d.currency!==currency)return null;
+ if(no&&!d.id.toLowerCase().includes(no)&&!d.billNo.toLowerCase().includes(no))return null;
+ total+=d.apAmount;paid+=d.paid;balance+=d.balance;profit+=d.profitAmount||0;
+ var symbol=d.currency==='USD'?'$':'¥';
+ return '
'+
+ '详情 '+(d.balance>0&&d.status==='生效'?'部分付款 ':'')+''+d.id+' '+d.supplier+' '+d.feeType+' '+d.currency+' '+
+ ''+symbol+d.apAmount.toLocaleString()+' '+symbol+d.paid.toLocaleString()+' '+symbol+d.balance.toLocaleString()+' '+
+ ''+d.billNo+' '+d.period+' '+d.genDate+' '+d.dueDate+' '+
+ ''+d.payStatus+' '+d.approveStatus+' '+
+ ''+d.hasProfit+' '+symbol+(d.profitAmount||0).toLocaleString()+' '+d.creator+' '+(d.reviewer||'-')+' '+d.status+' ';
+ }).filter(Boolean);
+ tb.innerHTML=rows.length?rows.join(''):'
暂无匹配数据 ';
+ document.getElementById('sap-total').textContent='¥'+total.toLocaleString();
+ document.getElementById('sap-paid').textContent='¥'+paid.toLocaleString();
+ document.getElementById('sap-pending').textContent='¥'+balance.toLocaleString();
+ document.getElementById('sap-profit').textContent='¥'+profit.toLocaleString();
+}
+
+function resetSettlementAp(){
+ document.getElementById('sap-status').selectedIndex=0;
+ document.getElementById('sap-supplier').selectedIndex=0;
+ document.getElementById('sap-currency').selectedIndex=0;
+ document.getElementById('sap-no').value='';
+ renderSettleAp();
+}
+
+var currentSettlementDetail=null;
+
+function settlementDetailRecord(){
+ if(!currentSettlementDetail)return null;
+ var list=currentSettlementDetail.type==='ar'?settlementArData:settlementApData;
+ return list.find(function(d){return d.id===currentSettlementDetail.id;})||null;
+}
+
+function openSettlementDetail(type,id){
+ currentSettlementDetail={type:type,id:id};
+ switchPage('settlement-detail');
+ var main=document.getElementById('mainContent');
+ if(main)main.scrollTop=0;
+ window.scrollTo(0,0);
+ renderSettlementDetail();
+}
+
+function backFromSettlementDetail(){
+ var page=currentSettlementDetail&¤tSettlementDetail.type==='ap'?'settlement-ap':'settlement-ar';
+ switchPage(page);
+}
+
+function partialFromSettlementDetail(){
+ if(currentSettlementDetail)showPartialSettlement(currentSettlementDetail.type,currentSettlementDetail.id);
+}
+
+function renderSettlementDetail(){
+ var record=settlementDetailRecord();
+ if(!record)return;
+ var isAr=currentSettlementDetail.type==='ar';
+ var party=isAr?record.customer:record.supplier;
+ var total=isAr?record.arAmount:record.apAmount;
+ var done=isAr?record.received:record.paid;
+ var kind=isAr?'应收':'应付';
+ var action=isAr?'收款':'付款';
+ var symbol=record.currency==='USD'?'$':'¥';
+ var money=function(v){return symbol+Number(v||0).toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2});};
+ document.getElementById('settlement-detail-breadcrumb').textContent='结算单'+kind;
+ document.getElementById('settlement-detail-breadcrumb-no').textContent=record.id;
+ document.getElementById('settlement-detail-title').textContent=kind+'结算单 · '+record.id;
+ var statusEl=document.getElementById('settlement-detail-status');
+ statusEl.textContent=record.payStatus;
+ statusEl.className='tag '+(record.payStatus==='已结清'?'tag-green':record.payStatus.indexOf('部分')===0?'tag-orange':'tag-red');
+ document.getElementById('settlement-detail-total-label').textContent=kind+'金额';
+ document.getElementById('settlement-detail-done-label').textContent='已'+action+'金额';
+ document.getElementById('settlement-detail-total').textContent=money(total);
+ document.getElementById('settlement-detail-done').textContent=money(done);
+ document.getElementById('settlement-detail-balance').textContent=money(record.balance);
+ document.getElementById('settlement-detail-due').textContent=record.dueDate;
+ var days=Math.ceil((new Date(record.dueDate+'T23:59:59')-new Date())/86400000);
+ var dueHint=document.getElementById('settlement-detail-due-hint');
+ dueHint.textContent=record.balance===0?'已结清':days<0?'已逾期 '+Math.abs(days)+' 天':days===0?'今日到期':'距到期 '+days+' 天';
+ dueHint.style.color=record.balance===0?'#16a34a':days<=7?'#ef4444':'#64748b';
+ var partialBtn=document.getElementById('settlement-detail-partial-btn');
+ partialBtn.textContent='部分'+action;
+ partialBtn.style.display=record.balance>0&&record.status==='生效'?'inline-flex':'none';
+
+ var info=[
+ ['结算单号',record.id],[(isAr?'客户公司':'供应商'),party],['费用类型',record.feeType],['币种',record.currency],
+ ['关联账单',record.billNo],['业务期间',record.period],['生成日期',record.genDate],['到期日期',record.dueDate],
+ ['制单人',record.creator],['当前状态',record.status]
+ ];
+ document.getElementById('settlement-detail-info').innerHTML=info.map(function(item){return '
'+item[0]+' '+item[1]+'
';}).join('');
+ var approved=record.approveStatus==='已审批';
+ document.getElementById('settlement-detail-approval').innerHTML='
✓ 结算单已创建 '+record.creator+' · '+record.genDate+'
'+(approved?'✓':'…')+' '+record.approveStatus+' '+(record.reviewer||'等待审核人处理')+'
';
+
+ document.getElementById('settlement-detail-fee-done-label').textContent='已'+action+'金额';
+ document.getElementById('settlement-detail-fee-summary').textContent='共 1 项费用';
+ document.getElementById('tbody-settlement-detail-fee').innerHTML='
'+record.billNo+' '+record.feeType+' '+record.period+' '+record.currency+' '+money(total)+' '+money(done)+' '+money(record.balance)+' '+record.payStatus+' ';
+
+ var records=(record.paymentRecords||[]).slice();
+ var recorded=records.reduce(function(sum,r){return sum+Number(r.amount||0);},0);
+ if(done-recorded>0.001)records.push({amount:done-recorded,date:record.lastPaymentDate||record.genDate,method:'历史累计',reference:'—',remark:'系统期初数据',operator:record.creator});
+ document.getElementById('settlement-detail-record-title').textContent=action+'记录';
+ document.getElementById('settlement-detail-record-date-label').textContent=action+'日期';
+ document.getElementById('settlement-detail-record-count').textContent='共 '+records.length+' 条';
+ document.getElementById('tbody-settlement-detail-record').innerHTML=records.length?records.map(function(r,i){return '
'+(i+1)+' '+r.date+' '+money(r.amount)+' '+(r.method||'银行转账')+' '+(r.reference||'—')+' '+(r.remark||'—')+' '+(r.operator||'张经理')+' ';}).join(''):'
暂无'+action+'记录 ';
+}
+
+var currentPartialSettlement=null;
+
+function partialSettlementRecord(){
+ if(!currentPartialSettlement)return null;
+ var list=currentPartialSettlement.type==='ar'?settlementArData:settlementApData;
+ return list.find(function(d){return d.id===currentPartialSettlement.id;})||null;
+}
+
+function partialSettlementMoney(record,value){
+ var symbol=record.currency==='USD'?'$':'¥';
+ return symbol+Number(value||0).toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2});
+}
+
+function showPartialSettlement(type,id){
+ currentPartialSettlement={type:type,id:id};
+ var record=partialSettlementRecord();
+ if(!record)return;
+ var isAr=type==='ar';
+ var total=isAr?record.arAmount:record.apAmount;
+ var done=isAr?record.received:record.paid;
+ document.getElementById('partial-settlement-title').textContent=isAr?'部分收款登记':'部分付款登记';
+ document.getElementById('partial-settlement-no').textContent=record.id;
+ document.getElementById('partial-settlement-party-label').textContent=isAr?'客户公司':'供应商';
+ document.getElementById('partial-settlement-party').textContent=isAr?record.customer:record.supplier;
+ document.getElementById('partial-total-label').textContent=isAr?'应收金额':'应付金额';
+ document.getElementById('partial-done-label').textContent=isAr?'已收金额':'已付金额';
+ document.getElementById('partial-amount-label').textContent=isAr?'本次收款金额 *':'本次付款金额 *';
+ document.getElementById('partial-date-label').textContent=isAr?'收款日期 *':'付款日期 *';
+ document.getElementById('partial-method-label').textContent=isAr?'收款方式 *':'付款方式 *';
+ document.getElementById('partial-submit-btn').textContent=isAr?'确认收款':'确认付款';
+ document.getElementById('partial-total').textContent=partialSettlementMoney(record,total);
+ document.getElementById('partial-done').textContent=partialSettlementMoney(record,done);
+ document.getElementById('partial-balance').textContent=partialSettlementMoney(record,record.balance);
+ var amount=document.getElementById('partial-amount');
+ amount.value='';amount.max=record.balance;amount.placeholder='最多 '+partialSettlementMoney(record,record.balance);
+ var now=new Date(),pad=function(n){return String(n).padStart(2,'0');};
+ document.getElementById('partial-date').value=now.getFullYear()+'-'+pad(now.getMonth()+1)+'-'+pad(now.getDate());
+ document.getElementById('partial-method').selectedIndex=0;
+ document.getElementById('partial-reference').value='';
+ document.getElementById('partial-remark').value='';
+ document.getElementById('partial-after-balance').textContent=partialSettlementMoney(record,record.balance);
+ showModal('modal-partial-settlement');
+ setTimeout(function(){amount.focus();},80);
+}
+
+function updatePartialSettlementPreview(){
+ var record=partialSettlementRecord();
+ if(!record)return;
+ var amount=Number(document.getElementById('partial-amount').value)||0;
+ document.getElementById('partial-after-balance').textContent=partialSettlementMoney(record,Math.max(0,record.balance-amount));
+}
+
+function confirmPartialSettlement(){
+ var record=partialSettlementRecord();
+ if(!record)return;
+ var isAr=currentPartialSettlement.type==='ar';
+ var amount=Number(document.getElementById('partial-amount').value);
+ var date=document.getElementById('partial-date').value;
+ if(!amount||amount<=0){showToast('请输入有效的'+(isAr?'收款':'付款')+'金额','warning');return;}
+ if(amount>record.balance){showToast('本次金额不能超过当前余额','warning');return;}
+ if(!date){showToast('请选择'+(isAr?'收款':'付款')+'日期','warning');return;}
+ if(isAr)record.received=Number((record.received+amount).toFixed(2));
+ else record.paid=Number((record.paid+amount).toFixed(2));
+ var total=isAr?record.arAmount:record.apAmount;
+ var done=isAr?record.received:record.paid;
+ record.balance=Number(Math.max(0,total-done).toFixed(2));
+ record.payStatus=record.balance===0?'已结清':(isAr?'部分收款':'部分付款');
+ record.lastPaymentDate=date;
+ if(!record.paymentRecords)record.paymentRecords=[];
+ record.paymentRecords.unshift({amount:amount,date:date,method:document.getElementById('partial-method').value,reference:document.getElementById('partial-reference').value,remark:document.getElementById('partial-remark').value});
+ hideModal('modal-partial-settlement');
+ if(isAr)renderSettlementAr();else renderSettleAp();
+ if(document.getElementById('page-settlement-detail').classList.contains('active'))renderSettlementDetail();
+ showToast((isAr?'收款':'付款')+'登记成功,剩余余额 '+partialSettlementMoney(record,record.balance),'success');
+ currentPartialSettlement=null;
}
var supplierData=[
@@ -18328,5 +19420,139 @@ function cancelRelease(){
+