diff --git a/static/app.js b/static/app.js
index 8b4a1a2..5d96735 100644
--- a/static/app.js
+++ b/static/app.js
@@ -421,16 +421,43 @@ function renderProducts() {
function renderFinance() {
const rows = state.data.finance.map((x) => [x.month, x.category, money(x.amount), text(x.notes)]);
document.querySelector("#finance").innerHTML = `
- ${card(`
收入、毛利、成本/费用、净利月度曲线
`, "p-5")}
+ ${card(`
收入、毛利、成本/费用、净利月度曲线
`, "p-5")}
${card(formHtml([
{ label: "日期", input: `
` },
{ label: "类型", input: `
` },
{ label: "金额/万", input: `
` },
{ label: "费用说明", input: `
` },
], { handler: "createFinance", text: "新增明细" }), "p-4")}
- ${card(`
明细列表 (${state.data.finance.length})
${renderTable(["日期", "类型", "金额", "备注"], rows)}
`, "p-4")}
+ ${card(`
明细列表 (${state.data.finance.length})
${renderTable(["日期", "类型", "金额", "备注"], rows)}`, "p-4")}
`;
- renderChartOn("financeChart2", state.data.financeMonthly);
+ if (window.lucide) window.lucide.createIcons();
+}
+window.toggleFinanceChart = () => {
+ const wrap = document.querySelector("#financeChartWrap");
+ const icon = document.querySelector("#financeChartIcon");
+ if (!wrap) return;
+ wrap.classList.toggle("hidden");
+ icon.classList.toggle("rotate-90");
+ if (!wrap.classList.contains("hidden") && !state.chart2) renderFinanceChart();
+};
+function renderFinanceChart() {
+ const { financeMonthly } = state.data;
+ const canvas = document.querySelector("#financeChart2");
+ if (!canvas || !window.Chart) return;
+ if (state.chart2) state.chart2.destroy();
+ state.chart2 = new Chart(canvas, {
+ type: "line",
+ data: {
+ labels: financeMonthly.map((x) => x.month),
+ datasets: [
+ { label: "收入", data: financeMonthly.map((x) => x.revenue), borderColor: "#2563eb", tension: 0.3 },
+ { label: "毛利", data: financeMonthly.map((x) => x.gross_profit), borderColor: "#059669", tension: 0.3 },
+ { label: "成本/费用", data: financeMonthly.map((x) => x.cost_expense), borderColor: "#d97706", tension: 0.3 },
+ { label: "净利", data: financeMonthly.map((x) => x.net_profit), borderColor: "#7c3aed", tension: 0.3 },
+ ],
+ },
+ options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: "bottom", labels: { boxWidth: 12, font: { size: 11 } } } }, scales: { x: { ticks: { font: { size: 11 } }, grid: { display: false } }, y: { ticks: { font: { size: 11 } } } } },
+ });
}
function renderChartOn(id, data) {