From 1e82ca73d9c0fd7c25b82e63f151249a5aa050a1 Mon Sep 17 00:00:00 2001 From: mac Date: Wed, 8 Jul 2026 17:45:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=AE=A1=E5=88=92=E8=B4=B9=E7=94=A8?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E5=8D=A1=E9=A1=BF+=E6=9C=88=E5=BA=A6?= =?UTF-8?q?=E6=80=BB=E8=A7=88=E5=A2=9E=E5=8A=A0=E5=9B=9E=E6=AC=BE=E7=8E=B0?= =?UTF-8?q?=E9=87=91=E6=B5=81=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - plan_expense.js: savePlanExpense/deletePlanExpItem改用api()+load() - 去掉多余的applyUserTenants和手动fetch bootstrap - plan.js月度总览增加回款和项目现金流两行 - 版本号 v1.0.0.33 --- static/modules/plan.js | 13 ++++++---- static/modules/plan_expense.js | 43 +++++++++++++++++----------------- templates/index.html | 2 +- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/static/modules/plan.js b/static/modules/plan.js index e162e66..8c5525e 100644 --- a/static/modules/plan.js +++ b/static/modules/plan.js @@ -1010,26 +1010,29 @@ function renderPlanOverview() { annualSums.payment += fm[i].payment; annualSums.paid += fm[i].paid; } const mLbl = ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']; - const LABELS = ['合同金额','确收金额','确收毛利','成本','已付']; + const LABELS = ['合同金额','确收金额','确收毛利','成本','已付','回款','项目现金流']; // 每行的年度累计 + 12个月值 const annualVals = [ annualSums.sign, annualSums.revenue, annualSums.gross, annualSums.cost, annualSums.paid, + annualSums.payment, annualSums.payment - annualSums.paid, ]; - // 字段映射: sign, revenue, gross, cost, profit(=gross-cost), payment, paid, cashflow(=payment-paid) - const fmFields = ['sign','revenue','gross','cost','paid']; + // 字段映射: sign, revenue, gross, cost, paid, payment, cashflow(=payment-paid) + const fmFields = ['sign','revenue','gross','cost','paid','payment',null]; var thead = '指标年度累计'; for (var mi = 0; mi < 12; mi++) { thead += '' + mLbl[mi] + ''; } thead += ''; var tbody = ''; - for (var ri = 0; ri < 5; ri++) { + for (var ri = 0; ri < 7; ri++) { var rowHtml = '' + LABELS[ri] + ''; rowHtml += '' + moneyIntL(annualVals[ri]) + ''; for (var mi = 0; mi < 12; mi++) { var val = 0; if (fm[mi]) { - var fk = fmFields[ri]; if (fk) val = fm[mi][fk] || 0; + if (ri === 6) { val = (fm[mi].payment || 0) - (fm[mi].paid || 0); } + else { var fk = fmFields[ri]; if (fk) val = fm[mi][fk] || 0; } } var cls = 'text-slate-700'; + if (ri === 6) cls = val >= 0 ? 'text-green-600' : 'text-red-600'; rowHtml += '' + moneyIntL(val) + ''; } tbody += rowHtml + ''; diff --git a/static/modules/plan_expense.js b/static/modules/plan_expense.js index f46a2f4..88b6312 100644 --- a/static/modules/plan_expense.js +++ b/static/modules/plan_expense.js @@ -184,36 +184,35 @@ window.savePlanExpense = async function(event) { if (data.amount === '' || data.amount === undefined) data.amount = 0; if (data.incurred_amount === '' || data.incurred_amount === undefined) data.incurred_amount = 0; if (!data.status) data.status = '计入费用'; - var isEdit = !!data.expense_id; + var id = data.expense_id; delete data.expense_id; + data.tenant = state.tenant; - var id = form.querySelector('[name="expense_id"]').value; - var url = isEdit ? "/api/planExpense/" + id : "/api/planExpense"; - var method = isEdit ? "PUT" : "POST"; - - var resp = await fetch(url, { method: method, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ data: Object.assign({}, data, { tenant: state.tenant }) }) }); - if (!resp.ok) { var err = await resp.text(); alert("保存失败:" + err); return; } - - var bResp = await fetch("/api/bootstrap?tenant=" + encodeURIComponent(state.tenant)); - if (bResp.ok) { - var bd = await bResp.json(); - state.data = bd; - applyUserTenants(); - renderPlanExpense(); + try { + if (id) { + await api("/api/planExpense/" + id, { method: "PUT", body: JSON.stringify({ data }) }); + } else { + await api("/api/planExpense", { method: "POST", body: JSON.stringify({ data }) }); + } + } catch (error) { + toast("保存失败:" + error.message, "error"); + return; } closePlanExpModal(); + await load(); + renderPlanExpense(); }; window.deletePlanExpItem = async function() { var id = document.querySelector("#planExpenseModal form [name='expense_id']").value; if (!id || !confirm("确定删除?")) return; - var resp = await fetch("/api/planExpense/" + id, { method: "DELETE" }); - if (!resp.ok) { alert("删除失败"); return; } - var bResp = await fetch("/api/bootstrap?tenant=" + encodeURIComponent(state.tenant)); - if (bResp.ok) { - var bd = await bResp.json(); - state.data = bd; - applyUserTenants(); - renderPlanExpense(); + try { + await api("/api/planExpense/" + id, { method: "DELETE" }); + } catch (error) { + toast("删除失败:" + error.message, "error"); + return; } + closePlanExpModal(); + await load(); + renderPlanExpense(); }; diff --git a/templates/index.html b/templates/index.html index 88cd957..1cbbd3f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -80,7 +80,7 @@
-

OPC Manager v1.0.0.32

+

OPC Manager v1.0.0.33

科普 OPC 工作台