From 39f2b679a160fb01466bd72ea5feed3bbd724393 Mon Sep 17 00:00:00 2001 From: mac Date: Tue, 23 Jun 2026 17:17:36 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=9B=9E=E6=AC=BE/=E8=B4=B9=E7=94=A8=E5=8D=A1=E7=89=87=20+=20?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=8F=A3=E5=BE=84=E5=AF=B9=E9=BD=90=20+=20UI?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增回款金额、费用金额 2 个卡片(5 列布局) - 卡片标题统一为 年度累计/季度累计/本月新增 - 季度计算改为动态本季度(不再写死 Q2) - 卡片数字统一取整(moneyInt) - 财务趋势图只统计已签约项目(与卡片口径对齐) - net_profit 字段重命名为 gross(消除命名误导) - 近期动态删除图标改为 trash-2(与附件删除一致) --- backend/flask_app.py | 37 +++++++++++++++++++++++++++---------- static/modules/home.js | 37 ++++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/backend/flask_app.py b/backend/flask_app.py index 69ba75b..2bf15c9 100644 --- a/backend/flask_app.py +++ b/backend/flask_app.py @@ -685,7 +685,7 @@ def attach_common(conn, resource, items): def monthly_finance(conn, tenant="科普·无界"): months = [f"2026-{m:02d}" for m in range(1, 13)] pfs = rows(conn, - "SELECT sign_amount, sign_month, status, budget_data FROM project_finances WHERE tenant=?", + "SELECT sign_amount, sign_month, status, budget_data FROM project_finances WHERE tenant=? AND status='已签约'", [tenant]) # 预解析 budget_data:{pf_index: {month_key: {rev, gross, payment, cost}}} @@ -722,7 +722,7 @@ def monthly_finance(conn, tenant="科普·无界"): data.append({ "month": month, "revenue": revenue, "labor": 0, "expense": 0, "purchase": 0, - "net_profit": gross, + "gross": gross, "sign": sign, "payment": payment, "cost": cost, }) return data @@ -777,22 +777,33 @@ def bootstrap(): total += float(b.get(field) or 0) return total + # 本季度月份范围(Q1=1-3, Q2=4-6, Q3=7-9, Q4=10-12),基于当前月 + _now_month = date.today().month + _q_start = ((_now_month - 1) // 3) * 3 + 1 + _q_range = range(_q_start, _q_start + 3) rev_annual = sum_budget("rev", range(1, 13)) gross_annual = sum_budget("gross", range(1, 13)) - rev_q2 = sum_budget("rev", range(4, 7)) - gross_q2 = sum_budget("gross", range(4, 7)) - rev_month = sum_budget("rev", [6]) - gross_month = sum_budget("gross", [6]) + rev_q2 = sum_budget("rev", _q_range) + gross_q2 = sum_budget("gross", _q_range) + rev_month = sum_budget("rev", [_now_month]) + gross_month = sum_budget("gross", [_now_month]) + payment_annual = sum_budget("payment", range(1, 13)) + cost_annual = sum_budget("cost", range(1, 13)) + payment_q2 = sum_budget("payment", _q_range) + cost_q2 = sum_budget("cost", _q_range) + payment_month = sum_budget("payment", [_now_month]) + cost_month = sum_budget("cost", [_now_month]) # Contract aggregates — from project_finances (经营管理项目) def pf_status_sum(status): return sum(x["sign_amount"] or 0 for x in pfs if x["status"] == status) signed_amount = pf_status_sum("已签约") # 年度签约 = 所有已签约项目 2026 年的签约金额 signed_annual = sum(x["sign_amount"] or 0 for x in pfs if x["status"] == "已签约") - # Q2 签约 = 签约月份在 2026-04~2026-06 的已签约项目 - signed_q2 = sum(x["sign_amount"] or 0 for x in pfs if x["status"] == "已签约" and (x.get("sign_month") or "")[:7] in ["2026-04","2026-05","2026-06"]) - # 本月签约 = 签约月份为 2026-06 的已签约项目 - signed_month = sum(x["sign_amount"] or 0 for x in pfs if x["status"] == "已签约" and (x.get("sign_month") or "") == "2026-06") + # 本季度签约 = 签约月份在当前季度的已签约项目 + _q_months = [f"2026-{m:02d}" for m in _q_range] + signed_q2 = sum(x["sign_amount"] or 0 for x in pfs if x["status"] == "已签约" and (x.get("sign_month") or "")[:7] in _q_months) + # 本月签约 = 签约月份为当月的已签约项目 + signed_month = sum(x["sign_amount"] or 0 for x in pfs if x["status"] == "已签约" and (x.get("sign_month") or "")[:7] == f"2026-{_now_month:02d}") pipeline_amount = sum(x["expected_contract_amount"] or 0 for x in operations if x["project_status"] not in ["已签约","已丢单","已归档","已完成"]) signed_not_executed = sum(x["expected_contract_amount"] or 0 for x in operations if x["project_type"] == "execution" and x["execution_progress"] < 100) summary = { @@ -819,6 +830,12 @@ def bootstrap(): "revenue_q2": rev_q2, "gross_annual": gross_annual, "gross_q2": gross_q2, + "payment_annual": payment_annual, + "payment_q2": payment_q2, + "payment_month": payment_month, + "cost_annual": cost_annual, + "cost_q2": cost_q2, + "cost_month": cost_month, "signed_not_executed": signed_not_executed, }, "recent": q("SELECT * FROM follow_up_records WHERE tenant=? ORDER BY id DESC LIMIT 8", tenant), diff --git a/static/modules/home.js b/static/modules/home.js index 9932ddb..f809dea 100644 --- a/static/modules/home.js +++ b/static/modules/home.js @@ -3,22 +3,33 @@ function renderHome() { const { summary, financeMonthly } = state.data; const m = summary.metrics; + const moneyInt = (v) => `${Math.round(Number(v || 0)).toLocaleString("zh-CN")} 元`; const rows1 = [ - ["年度累计签约", money(m.signed_annual || m.signed_amount)], - ["Q2 累计签约", money(m.signed_q2 || 0)], - ["本月新增签约", money(m.signed_month || 0)], + ["年度累计", moneyInt(m.signed_annual || m.signed_amount)], + ["季度累计", moneyInt(m.signed_q2 || 0)], + ["本月新增", moneyInt(m.signed_month || 0)], ]; const rows2 = [ - ["年度累计确收", money(m.revenue_annual)], - ["Q2 累计确收", money(m.revenue_q2)], - ["本月新增确收", money(m.monthly_revenue)], + ["年度累计", moneyInt(m.revenue_annual)], + ["季度累计", moneyInt(m.revenue_q2)], + ["本月新增", moneyInt(m.monthly_revenue)], ]; const rows3 = [ - ["年度累计毛利", money(m.gross_annual)], - ["Q2 累计毛利", money(m.gross_q2)], - ["本月新增毛利", money(m.monthly_net_profit)], + ["年度累计", moneyInt(m.gross_annual)], + ["季度累计", moneyInt(m.gross_q2)], + ["本月新增", moneyInt(m.monthly_net_profit)], ]; - const tblCard = (title, rows) => card(`

${title}

${rows.map(([label, value]) => ``).join("")}
${label}${value}
`, "p-4"); + const rows4 = [ + ["年度累计", moneyInt(m.payment_annual || 0)], + ["季度累计", moneyInt(m.payment_q2 || 0)], + ["本月新增", moneyInt(m.payment_month || 0)], + ]; + const rows5 = [ + ["年度累计", moneyInt(m.cost_annual || 0)], + ["季度累计", moneyInt(m.cost_q2 || 0)], + ["本月新增", moneyInt(m.cost_month || 0)], + ]; +const tblCard = (title, rows) => card(`

${title}

${rows.map(([label, value]) => ``).join("")}
${label}${value}
`, "p-4"); document.querySelector("#home").innerHTML = `
@@ -29,13 +40,13 @@ function renderHome() { ["产品迭代", m.upcoming_products, "products"], ].map(([label, value, tab]) => ``).join("")}
-
${tblCard("合同金额", rows1)}${tblCard("确收金额", rows2)}${tblCard("确收毛利", rows3)}
+
${tblCard("合同金额", rows1)}${tblCard("确收金额", rows2)}${tblCard("确收毛利", rows3)}${tblCard("回款金额", rows4)}${tblCard("费用金额", rows5)}
${card(`

月度签约趋势

2026
`, "p-4")} ${card(`

月度确收与毛利

2026
`, "p-4")} ${card(`

月度回款与费用

2026
`, "p-4")}
- ${card(`

近期动态

${summary.recent.map((r) => `
${r.content}
${r.followed_at}
`).join("")}
`, "p-5")} + ${card(`

近期动态

${summary.recent.map((r) => `
${r.content}
${r.followed_at}
`).join("")}
`, "p-5")}
`; renderCharts(financeMonthly); @@ -81,7 +92,7 @@ function renderCharts(data) { type: "line", data: { labels, datasets: [ { label: "确收", data: data.map((x) => x.revenue || 0), borderColor: "#2563eb", backgroundColor: "rgba(37,99,235,0.06)", fill: true, tension: 0.3 }, - { label: "毛利", data: data.map((x) => x.net_profit || 0), borderColor: "#059669", backgroundColor: "rgba(5,150,105,0.06)", fill: true, tension: 0.3 }, + { label: "毛利", data: data.map((x) => x.gross || 0), borderColor: "#059669", backgroundColor: "rgba(5,150,105,0.06)", fill: true, tension: 0.3 }, ]}, options: baseOpts, });