From 2c20900e758b5a3c1a49e7203220cd7d4554ebac Mon Sep 17 00:00:00 2001 From: mac Date: Sat, 11 Jul 2026 11:44:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=8F=E8=90=A5=E6=9C=88=E6=8A=A5?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E6=94=B9=E5=90=8D+=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E4=BC=98=E5=8C=96+=E5=88=87=E6=8D=A2=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8F=B0=E9=BB=98=E8=AE=A4=E7=BB=8F=E8=90=A5=E6=9C=88=E6=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 业务线经营情况→部门损益情况,副标题改为部门利润公式 - 业务线现金流→部门现金流,副标题改为部门现金流公式 - 财务月度/季度概览→项目经营详情 - 3个卡片主副标题加大+间距对齐+颜色加深 - 签约月份/添加月份/平台费用月份默认当前月份 - 切换工作台默认显示经营月报 - 版本号 v1.2.0.21 --- static/modules/expense.js | 3 ++- static/modules/finance.js | 22 +++++++++++----------- static/modules/plan.js | 22 +++++++++++----------- static/modules/plan_expense.js | 3 ++- static/modules/utils.js | 9 +++++---- templates/index.html | 2 +- 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/static/modules/expense.js b/static/modules/expense.js index 515dd03..72b8d03 100644 --- a/static/modules/expense.js +++ b/static/modules/expense.js @@ -108,11 +108,12 @@ function renderExpense() { } // 模态框 monthOpts for form (with current value preselected) + var curMonth = thisYear + '-' + String(now.getMonth() + 1).padStart(2, '0'); var modalMonthOpts = ''; for (var yr2 = thisYear - 1; yr2 <= thisYear + 1; yr2++) for (var m2 = 1; m2 <= 12; m2++) { var mv2 = yr2 + '-' + String(m2).padStart(2, '0'); - modalMonthOpts += ''; + modalMonthOpts += ''; } var statusOpts = STATUS_OPTIONS.map(function(s) { return ''; }).join(''); diff --git a/static/modules/finance.js b/static/modules/finance.js index cb14b86..0ac6907 100644 --- a/static/modules/finance.js +++ b/static/modules/finance.js @@ -144,7 +144,7 @@ function renderFinance() {
- +
@@ -517,7 +517,7 @@ window.openFinanceModal = () => { modal.classList.remove("hidden"); }; -window.addRevpayRow = (month = '', rev = '', gross = '', payment = '', rev_note = '') => { +window.addRevpayRow = (month = new Date().getFullYear() + '-' + String(new Date().getMonth() + 1).padStart(2, '0'), rev = '', gross = '', payment = '', rev_note = '') => { const tbody = document.querySelector("#revpayTbody"); if (!tbody) return; const row = document.createElement("tr"); @@ -531,7 +531,7 @@ window.addRevpayRow = (month = '', rev = '', gross = '', payment = '', rev_note if (window.lucide) window.lucide.createIcons(); }; -window.addCostRow = (month = '', expense_type = '', cost = '', paid = '', exp_note = '') => { +window.addCostRow = (month = new Date().getFullYear() + '-' + String(new Date().getMonth() + 1).padStart(2, '0'), expense_type = '', cost = '', paid = '', exp_note = '') => { const tbody = document.querySelector("#costTbody"); if (!tbody) return; const row = document.createElement("tr"); @@ -1043,7 +1043,7 @@ function renderFinanceOverview() { } deptTbody += rowHtml + ''; } - var deptCard = card('

业务线经营情况

毛利 - 平台费用 = 利润

' + deptThead + '' + deptTbody + '
', 'p-4'); + var deptCard = card('

部门损益情况 部门利润 = 所有项目产生的毛利 - 部门 1 级产生的人力成本,研发成本,差旅和其他支出

' + deptThead + '' + deptTbody + '
', 'p-4'); // 业务线现金流卡片 var cfMonthly = [0,0,0,0,0,0,0,0,0,0,0,0]; @@ -1062,7 +1062,7 @@ function renderFinanceOverview() { var cfRows = [ { label: '项目现金流', vals: cfMonthly, annual: cfAnnual }, { label: '平台费用(支出)', vals: expPaidMonthly, annual: expPaidAnnual }, - { label: '业务线现金流', vals: blCfMonthly, annual: blCfAnnual } + { label: '部门现金流', vals: blCfMonthly, annual: blCfAnnual } ]; var cfTbody = ''; for (var cfri = 0; cfri < 3; cfri++) { @@ -1078,12 +1078,12 @@ function renderFinanceOverview() { } cfTbody += cfRowHtml + ''; } - var cfCard = card('

业务线现金流

项目现金流 - 平台费用(支出)= 业务线现金流

' + deptThead + '' + cfTbody + '
', 'p-4'); + var cfCard = card('

部门现金流 部门现金流=所有项目产生的现金流 - 部门一级因费用产生的现金流出或流入

' + deptThead + '' + cfTbody + '
', 'p-4'); document.querySelector("#financeOverview").innerHTML = '
' + deptCard + cfCard + - card('

业务(项目)财务月度概览

合同 → 确收 → 毛利 → 成本 → 支出

' + thead + '' + tbody + '
', 'p-4') + + card('

项目经营详情 所有项目产生的签单,确收,毛利,回款,当期成本,当期流出,现金流

' + thead + '' + tbody + '
', 'p-4') + '
' + card('

月度签约趋势

2026
', 'p-4') + card('

月度确收与毛利

2026
', 'p-4') + @@ -1196,7 +1196,7 @@ function renderFinanceQuarterlyOverview() { var cfRows = [ { label: '项目现金流', vals: cfQ, annual: cfAnnual }, { label: '平台费用(已付)', vals: expPaidQ, annual: expPaidAnnual }, - { label: '业务线现金流', vals: blCfQ, annual: blCfAnnual } + { label: '部门现金流', vals: blCfQ, annual: blCfAnnual } ]; var cfTbody = ''; for (var cfri = 0; cfri < 3; cfri++) { @@ -1213,9 +1213,9 @@ function renderFinanceQuarterlyOverview() { } document.querySelector("#financeQuarterlyOverview").innerHTML = '
' + - card('

业务(项目)财务季度概览

合同 → 确收 → 毛利 → 成本 → 支出 → 回款 → 项目现金流

' + thead + '' + tbody + '
', 'p-4') + - card('

业务线经营情况

毛利 - 平台费用 = 利润

' + deptThead + '' + deptTbody + '
', 'p-4') + - card('

业务线现金流

项目现金流 - 平台费用(已付)= 业务线现金流

' + deptThead + '' + cfTbody + '
', 'p-4') + + card('

项目经营详情 所有项目产生的签单,确收,毛利,回款,当期成本,当期流出,现金流

' + thead + '' + tbody + '
', 'p-4') + + card('

部门损益情况 部门利润 = 所有项目产生的毛利 - 部门 1 级产生的人力成本,研发成本,差旅和其他支出

' + deptThead + '' + deptTbody + '
', 'p-4') + + card('

部门现金流 部门现金流=所有项目产生的现金流 - 部门一级因费用产生的现金流出或流入

' + deptThead + '' + cfTbody + '
', 'p-4') + '
'; if (window.lucide) window.lucide.createIcons(); } diff --git a/static/modules/plan.js b/static/modules/plan.js index e4d8f5c..4ed286f 100644 --- a/static/modules/plan.js +++ b/static/modules/plan.js @@ -143,7 +143,7 @@ function renderPlan() {
- +
@@ -562,7 +562,7 @@ window.openPlanModal = () => { modal.classList.remove("hidden"); }; -window.planAddRevpayRow = (month = '', rev = '', gross = '', payment = '', rev_note = '') => { +window.planAddRevpayRow = (month = new Date().getFullYear() + '-' + String(new Date().getMonth() + 1).padStart(2, '0'), rev = '', gross = '', payment = '', rev_note = '') => { const tbody = document.querySelector("#plan_revpayTbody"); if (!tbody) return; const row = document.createElement("tr"); @@ -576,7 +576,7 @@ window.planAddRevpayRow = (month = '', rev = '', gross = '', payment = '', rev_n if (window.lucide) window.lucide.createIcons(); }; -window.planAddCostRow = (month = '', expense_type = '', cost = '', paid = '', exp_note = '') => { +window.planAddCostRow = (month = new Date().getFullYear() + '-' + String(new Date().getMonth() + 1).padStart(2, '0'), expense_type = '', cost = '', paid = '', exp_note = '') => { const tbody = document.querySelector("#plan_costTbody"); if (!tbody) return; const row = document.createElement("tr"); @@ -1133,7 +1133,7 @@ function renderPlanOverview() { } deptTbody += rowHtml + ''; } - var deptCard = card('

业务线经营情况

毛利 - 平台费用 = 利润

' + deptThead + '' + deptTbody + '
', 'p-4'); + var deptCard = card('

部门损益情况 部门利润 = 所有项目产生的毛利 - 部门 1 级产生的人力成本,研发成本,差旅和其他支出

' + deptThead + '' + deptTbody + '
', 'p-4'); // 业务线现金流卡片 @@ -1152,7 +1152,7 @@ function renderPlanOverview() { var cfRows = [ { label: '项目现金流', vals: cfMonthly, annual: cfAnnual }, { label: '平台费用(已付)', vals: expPaidMonthly, annual: expPaidAnnual }, - { label: '业务线现金流', vals: blCfMonthly, annual: blCfAnnual } + { label: '部门现金流', vals: blCfMonthly, annual: blCfAnnual } ]; var cfTbody = ''; for (var cfri = 0; cfri < 3; cfri++) { @@ -1168,12 +1168,12 @@ function renderPlanOverview() { } cfTbody += cfRowHtml + ''; } - var cfCard = card('

业务线现金流

项目现金流 - 平台费用(已付)= 业务线现金流

' + deptThead + '' + cfTbody + '
', 'p-4'); + var cfCard = card('

部门现金流 部门现金流=所有项目产生的现金流 - 部门一级因费用产生的现金流出或流入

' + deptThead + '' + cfTbody + '
', 'p-4'); document.querySelector("#planOverview").innerHTML = '
' + deptCard + cfCard + - card('

业务(项目)财务概览

合同 → 确收 → 毛利 → 成本 → 已付

' + thead + '' + tbody + '
', 'p-4') + + card('

项目经营详情 所有项目产生的签单,确收,毛利,回款,当期成本,当期流出,现金流

' + thead + '' + tbody + '
', 'p-4') + '
' + card('

月度签约趋势

2026
', 'p-4') + card('

月度确收与毛利

2026
', 'p-4') + @@ -1289,7 +1289,7 @@ function renderPlanQuarterlyOverview() { var cfRows = [ { label: '项目现金流', vals: cfQ, annual: cfAnnual }, { label: '平台费用(已付)', vals: expPaidQ, annual: expPaidAnnual }, - { label: '业务线现金流', vals: blCfQ, annual: blCfAnnual } + { label: '部门现金流', vals: blCfQ, annual: blCfAnnual } ]; var cfTbody = ''; for (var cfri = 0; cfri < 3; cfri++) { @@ -1306,9 +1306,9 @@ function renderPlanQuarterlyOverview() { } document.querySelector("#planQuarterlyOverview").innerHTML = '
' + - card('

业务线经营情况

毛利 - 平台费用 = 利润

' + deptThead + '' + deptTbody + '
', 'p-4') + - card('

业务线现金流

项目现金流 - 平台费用(已付)= 业务线现金流

' + deptThead + '' + cfTbody + '
', 'p-4') + - card('

业务(项目)财务季度概览

合同 → 确收 → 毛利 → 成本 → 支出 → 回款 → 项目现金流

' + thead + '' + tbody + '
', 'p-4') + + card('

部门损益情况 部门利润 = 所有项目产生的毛利 - 部门 1 级产生的人力成本,研发成本,差旅和其他支出

' + deptThead + '' + deptTbody + '
', 'p-4') + + card('

部门现金流 部门现金流=所有项目产生的现金流 - 部门一级因费用产生的现金流出或流入

' + deptThead + '' + cfTbody + '
', 'p-4') + + card('

项目经营详情 所有项目产生的签单,确收,毛利,回款,当期成本,当期流出,现金流

' + thead + '' + tbody + '
', 'p-4') + '
'; if (window.lucide) window.lucide.createIcons(); } diff --git a/static/modules/plan_expense.js b/static/modules/plan_expense.js index ea0bc08..6847528 100644 --- a/static/modules/plan_expense.js +++ b/static/modules/plan_expense.js @@ -108,11 +108,12 @@ function renderPlanExpense() { } // 模态框 monthOpts for form (with current value preselected) + var curMonth = thisYear + '-' + String(now.getMonth() + 1).padStart(2, '0'); var modalMonthOpts = ''; for (var yr2 = thisYear - 1; yr2 <= thisYear + 1; yr2++) for (var m2 = 1; m2 <= 12; m2++) { var mv2 = yr2 + '-' + String(m2).padStart(2, '0'); - modalMonthOpts += ''; + modalMonthOpts += ''; } var statusOpts = STATUS_OPTIONS.map(function(s) { return ''; }).join(''); diff --git a/static/modules/utils.js b/static/modules/utils.js index 73e055a..037730a 100644 --- a/static/modules/utils.js +++ b/static/modules/utils.js @@ -5,13 +5,13 @@ const state = { data: null, tenant: localStorage.getItem("opc-active-tenant") || "科普·无界", opFilter: "all", - finFilter: "projects", + finFilter: "overview", selectedProject: null, taskQuery: "", taskView: localStorage.getItem("opc-task-view") || "detail", finView: "overview", finSort: null, // { key: 'col', asc: true } - planFilter: "projects", + planFilter: "overview", planYear: new Date().getFullYear(), finYear: new Date().getFullYear(), planStatusFilter: "all", @@ -390,9 +390,10 @@ window.switchTenant = async (tenant) => { localStorage.setItem("opc-active-tenant", tenant); document.querySelector("#workspaceTitle").textContent = tenant.replace("·无界", "") + " OPC 工作台"; if (typeof updateTenantLabel === "function") updateTenantLabel(); + state.planFilter = 'overview'; + state.finFilter = 'overview'; updateSidebarTabs(); - if (tenant === "总览") { state.planFilter = 'overview'; state.finFilter = 'overview'; switchTab("home"); } - else if (state.active === 'home') { state.active = 'plan'; localStorage.setItem("opc-active-tab", "plan"); document.querySelectorAll(".sidebar-tab").forEach((btn) => btn.classList.toggle("active", btn.dataset.tab === "plan")); document.querySelectorAll(".panel").forEach((panel) => panel.classList.toggle("active", panel.id === "plan")); } + if (state.active === 'home') { state.active = 'plan'; localStorage.setItem("opc-active-tab", "plan"); document.querySelectorAll(".sidebar-tab").forEach((btn) => btn.classList.toggle("active", btn.dataset.tab === "plan")); document.querySelectorAll(".panel").forEach((panel) => panel.classList.toggle("active", panel.id === "plan")); } await load(); }; diff --git a/templates/index.html b/templates/index.html index 5667480..adf544c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -76,7 +76,7 @@
-

OPC Manager v1.2.0.20

+

OPC Manager v1.2.0.21

科普 OPC 工作台