From f4b69449b2750689aaac3fbdd0302bbf0cb3f2f1 Mon Sep 17 00:00:00 2001 From: mac Date: Fri, 10 Jul 2026 22:32:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A2=84=E7=AE=97=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E5=8C=BA=E5=A2=9E=E5=8A=A0=E7=8A=B6=E6=80=81=E6=A0=87=E7=AD=BE?= =?UTF-8?q?(=E5=BE=85=E7=AD=BE=E7=BA=A6/=E5=B7=B2=E7=AD=BE=E7=BA=A6/?= =?UTF-8?q?=E5=8F=AA=E4=BB=98=E6=AC=BE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 月份后增加待签约|已签约|只付款3个状态筛选按钮 - 待签约: project_type为待签约 - 已签约: project_type为已签约 - 只付款: 只有成本/付款,确收/毛利/回款为空 - 三种视图(月度/季度/总视图)都支持过滤 - 版本号 v1.2.0.17 --- static/modules/plan.js | 23 +++++++++++++++++++---- static/modules/utils.js | 2 ++ templates/index.html | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/static/modules/plan.js b/static/modules/plan.js index 7dd85de..62f2324 100644 --- a/static/modules/plan.js +++ b/static/modules/plan.js @@ -109,7 +109,7 @@ function renderPlan() { const activeQ = state.planQuarter !== undefined ? state.planQuarter : Math.floor(nowD.getMonth() / 3); const activeMonths = qMonths[activeQ]; const yearOpts = [2024,2025,2026,2027]; - const finHeaderBase = `
|年份:|季度:${qLabels.map((q,i) => ``).join('')}|月度:${activeMonths.map(m => { const ms = `${state.planYear}-${String(m).padStart(2,'0')}`; return ``; }).join('')}
`; + const finHeaderBase = `
|年份:|季度:${qLabels.map((q,i) => ``).join('')}|月度:${activeMonths.map(m => { const ms = `${state.planYear}-${String(m).padStart(2,'0')}`; return ``; }).join('')}|
`; const finAddBtn = ``; const isOverviewMode = false; @@ -345,6 +345,21 @@ function renderPlan() { }; const fmtNoUnit = (v) => v ? `${Number(v||0).toLocaleString('zh-CN')}` : ''; + + // 状态过滤函数 + const filterByStatus = (items) => { + var sf = state.planStatusFilter || 'all'; + if (sf === 'all') return items; + return items.filter(d => { + if (sf === 'unsigned') return (d.pf.project_type || '待签约') === '待签约'; + if (sf === 'signed') return (d.pf.project_type || '待签约') === '已签约'; + if (sf === 'paymentonly') { + return (!d.rev && !d.gross && !d.payment) && (d.cost || d.paid); + } + return true; + }); + }; + const tdRow = (pf, rev, payment, cost, paid, gross) => { const cashflow = payment - paid; const payRVal = rev && payment ? Math.round(payment / rev * 100) : null; @@ -422,7 +437,7 @@ function renderPlan() { }); }); var sortK = state.planSort && state.planSort.key ? state.planSort.key.split('|')[1] : null; - dataItems = sortData(dataItems, sortK); + dataItems = filterByStatus(sortData(dataItems, sortK)); const rows = []; let sumRev = 0, sumPay = 0, sumCost = 0, sumPaid = 0, sumGross = 0; dataItems.forEach(d => { @@ -477,7 +492,7 @@ function renderPlan() { }); }); var sortK = state.planSort && state.planSort.key ? state.planSort.key.split('|')[1] : null; - dataItems = sortData(dataItems, sortK); + dataItems = filterByStatus(sortData(dataItems, sortK)); let sumRev = 0, sumPay = 0, sumCost = 0, sumPaid = 0, sumGross = 0; const rows = []; dataItems.forEach(d => { @@ -518,7 +533,7 @@ function renderPlan() { }); var sortK = null; if (state.planSort && state.planSort.key && state.planSort.key.startsWith('sig|')) sortK = state.planSort.key.split('|')[1]; - dataItems = sortData(dataItems, sortK); + dataItems = filterByStatus(sortData(dataItems, sortK)); let sumRev = 0, sumPay = 0, sumCost = 0, sumPaid = 0, sumGross = 0; const rows = []; dataItems.forEach(d => { diff --git a/static/modules/utils.js b/static/modules/utils.js index a66393c..8bdc3b9 100644 --- a/static/modules/utils.js +++ b/static/modules/utils.js @@ -14,6 +14,7 @@ const state = { planFilter: "projects", planYear: new Date().getFullYear(), finYear: new Date().getFullYear(), + planStatusFilter: "all", planView: "overview", planSort: null, proposalTab: "standard", @@ -355,6 +356,7 @@ window.setPlanView = (view) => { window.setPlanQuarter = (q) => { state.planQuarter = q; state.planView = 'quarterly'; renderPlan(); }; window.setPlanMonth = (month) => { state.planMonth = month; state.planView = 'monthly'; renderPlan(); }; window.setPlanYear = (year) => { state.planYear = parseInt(year); renderPlan(); }; +window.setPlanStatusFilter = (filter) => { state.planStatusFilter = filter; renderPlan(); }; window.switchPlanFilter = (filter) => { state.planFilter = filter; state.planSort = null; diff --git a/templates/index.html b/templates/index.html index ca4abb0..b00988d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -76,7 +76,7 @@
-

OPC Manager v1.2.0.16

+

OPC Manager v1.2.0.17

科普 OPC 工作台