diff --git a/static/modules/finance.js b/static/modules/finance.js
index 5d30463..620ec32 100644
--- a/static/modules/finance.js
+++ b/static/modules/finance.js
@@ -290,6 +290,7 @@ function renderFinance() {
return h;
};
const SIGNED_COLS = [
+ { key: '_expand', label: '' },
{ key: 'client_name', label: '客户' }, { key: 'customer_name', label: '项目名称' }, { key: 'sign_amount', label: '签约金额' },
{ key: 'rev', label: '已确收' }, { key: 'gross', label: '毛利' }, { key: 'gross_rate', label: '毛利率' },
{ key: 'payment', label: '回款' }, { key: 'pay_rate', label: '回款率' },
@@ -331,7 +332,24 @@ function renderFinance() {
const grossR = rev && gross ? Math.round(gross / rev * 100) + '%' : '—';
const cf = cashflow ? money(cashflow) : '—';
const cfCls = cashflow >= 0 ? 'text-green-600' : 'text-red-600';
- return `
| ${esc(pf.client_name || "")} | ${esc(pf.customer_name)} | ${money(pf.sign_amount)} | ${fmtNoUnit(rev)} | ${fmtNoUnit(gross)} | ${grossR} | ${fmtNoUnit(payment)} | ${payR} | ${fmtNoUnit(cost)} | ${fmtNoUnit(paid)} | ${paidR} | ${cf} |
`;
+ var budgetArr = [];
+ var expenseArr = [];
+ try { budgetArr = JSON.parse(pf.budget_data || "[]"); } catch(e) {}
+ try { expenseArr = JSON.parse(pf.expense_data || "[]"); } catch(e) {}
+ var detailRows = budgetArr.filter(function(b) {
+ var exp = expenseArr.find(function(e) { return e.month === (b.month || ''); }) || {};
+ var bRev = parseFloat(b.rev || 0), bGross = parseFloat(b.gross || 0), bPay = parseFloat(b.payment || 0);
+ var eCost = parseFloat(exp.cost || 0), ePaid = parseFloat(exp.paid || 0);
+ return bRev || bGross || bPay || eCost || ePaid;
+ }).map(function(b) {
+ var m = b.month || '';
+ var exp = expenseArr.find(function(e) { return e.month === m; }) || {};
+ var bRev = parseFloat(b.rev || 0), bGross = parseFloat(b.gross || 0), bPay = parseFloat(b.payment || 0);
+ var eCost = parseFloat(exp.cost || 0), ePaid = parseFloat(exp.paid || 0);
+ var bCf = bPay - ePaid;
+ return ' | | ' + m + ' | ' + (bRev ? money(bRev) : '—') + ' | ' + (bGross ? money(bGross) : '—') + ' | | ' + (bPay ? money(bPay) : '—') + ' | | ' + (eCost ? money(eCost) : '—') + ' | ' + (ePaid ? money(ePaid) : '—') + ' | | ' + (bCf ? money(bCf) : '—') + ' |
';
+ }).join('');
+ return ` | ${esc(pf.client_name || "")} | ${esc(pf.customer_name)} | ${money(pf.sign_amount)} | ${fmtNoUnit(rev)} | ${fmtNoUnit(gross)} | ${grossR} | ${fmtNoUnit(payment)} | ${payR} | ${fmtNoUnit(cost)} | ${fmtNoUnit(paid)} | ${paidR} | ${cf} |
| | 月份 | 确收 | 毛利 | | 回款 | | 成本 | 支出 | | 现金流 | ${detailRows}
|
`;
};
// 待签约简版行
const tdRowUnsigned = (pf, cost, gross) => {
@@ -752,6 +770,19 @@ window.deleteFinFollowup = async (event, followupId) => {
if (pfId) await loadFinFollowups(pfId);
};
+window.finToggleExpand = (pfId) => {
+ var row = document.getElementById('fin_expand_' + pfId);
+ var icon = document.getElementById('fin_expand_icon_' + pfId);
+ if (!row) return;
+ if (row.classList.contains('hidden')) {
+ row.classList.remove('hidden');
+ if (icon) { icon.setAttribute('data-lucide', 'chevron-down'); if (window.lucide) window.lucide.createIcons(); }
+ } else {
+ row.classList.add('hidden');
+ if (icon) { icon.setAttribute('data-lucide', 'chevron-right'); if (window.lucide) window.lucide.createIcons(); }
+ }
+};
+
window.openPfEditModal = (pfId) => {
const pf = (state.data.projectFinances || []).find(x => x.id === pfId);
if (!pf) return;
diff --git a/templates/index.html b/templates/index.html
index 771920f..5141179 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -76,7 +76,7 @@
-
OPC Manager v1.2.0.6
+
OPC Manager v1.2.0.7