diff --git a/VERSION_LOG.md b/VERSION_LOG.md
index f511553..619f4a6 100644
--- a/VERSION_LOG.md
+++ b/VERSION_LOG.md
@@ -1,5 +1,16 @@
# OPC Manager Version Log
+## v1.0.7 — 2026-06-04
+- 修复新增表单 async 后 `event.currentTarget` 丢失导致页面不刷新(影响所有新增按钮)
+- `createResource` 改用预存 form 引用 + try/catch 错误提示
+
+## v1.0.6 — 2026-06-04
+- 修复财务 Tab Chart 无限堆积:renderChartOn 缺少旧 chart 销毁 + state 跟踪
+- 财务图表容器加固定高度(300px),避免 resize 循环
+
+## v1.0.5 — 2026-06-04
+- "销售管理" Tab 改为"业务机会","目标客户"字段统一改为"业务机会"
+
## v1.0.4 — 2026-06-04
- CDN 全量本地化:Tailwind / Chart.js / Squire / Lucide 下载到 `static/vendor/`,不再依赖外部 CDN
diff --git a/static/app.js b/static/app.js
index 88e5acb..093671b 100644
--- a/static/app.js
+++ b/static/app.js
@@ -3,6 +3,7 @@ const state = {
data: null,
opFilter: "all",
chart: null,
+ chart2: null,
};
const money = (value) => `${Number(value || 0).toLocaleString("zh-CN")} 万`;
@@ -143,10 +144,15 @@ function formHtml(fields, button) {
async function createResource(event, resource) {
event.preventDefault();
- const data = Object.fromEntries(new FormData(event.currentTarget).entries());
- await api(`/api/${resource}`, { method: "POST", body: JSON.stringify({ data }) });
- event.currentTarget.reset();
- await load();
+ const form = event.currentTarget;
+ const data = Object.fromEntries(new FormData(form).entries());
+ try {
+ await api(`/api/${resource}`, { method: "POST", body: JSON.stringify({ data }) });
+ form.reset();
+ await load();
+ } catch (error) {
+ alert("创建失败:" + error.message);
+ }
}
window.createSales = (event) => createResource(event, "sales");
@@ -161,11 +167,11 @@ function renderSales() {
const salesClicks = state.data.sales.map((x) => ({ resource: "sales", id: x.id }));
document.querySelector("#sales").innerHTML = `
- ${card(`
收入、毛利、成本/费用、净利月度曲线
`, "p-5")}
+ ${card(`
收入、毛利、成本/费用、净利月度曲线
`, "p-5")}
${card(formHtml([
{ label: "月份", input: `
` },
{ label: "类型", input: `
` },
@@ -261,7 +267,8 @@ function renderFinance() {
function renderChartOn(id, data) {
const canvas = document.querySelector(`#${id}`);
if (!canvas || !window.Chart) return;
- new Chart(canvas, {
+ if (state.chart2) state.chart2.destroy();
+ state.chart2 = new Chart(canvas, {
type: "line",
data: {
labels: data.map((x) => x.month),
@@ -292,9 +299,9 @@ function openDrawer(resource, id) {
const item = list.find((x) => x.id === id);
const drawer = document.querySelector("#drawer");
const fields = resource === "sales"
- ? [["target_customer","目标客户"],["priority","优先级"],["status","状态"]]
+ ? [["target_customer","业务机会"],["priority","优先级"],["status","状态"]]
: resource === "operations"
- ? [["project_name","项目名称"],["project_version","项目版本"],["project_status","项目状态"],["current_stage","当前阶段"],["target_customer","目标客户"],["customer_need","客户需求"],["expected_contract_amount","预计签约金额"],["expected_sign_date","预计签约时间"],["sign_probability","签约概率"],["sop_stage","SOP 阶段"],["execution_progress","执行进度"],["current_deliverable","当前交付物"],["risks","风险与阻塞"],["next_action","下一步动作"]]
+ ? [["project_name","项目名称"],["project_version","项目版本"],["project_status","项目状态"],["current_stage","当前阶段"],["target_customer","业务机会"],["customer_need","客户需求"],["expected_contract_amount","预计签约金额"],["expected_sign_date","预计签约时间"],["sign_probability","签约概率"],["sop_stage","SOP 阶段"],["execution_progress","执行进度"],["current_deliverable","当前交付物"],["risks","风险与阻塞"],["next_action","下一步动作"]]
: resource === "proposals"
? [["customer_or_project_name","客户/项目"],["version","版本号"],["description","版本说明"],["created_date","创建日期"],["status","状态"]]
: [["product_name","产品名称"],["version","版本号"],["version_goal","版本目标"],["feature_list","核心功能清单"],["launch_date","上线日期"],["status","当前状态"],["notes","备注"]];
diff --git a/templates/index.html b/templates/index.html
index 0e24efc..2ea0e33 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -36,7 +36,7 @@