From a2ad9cafdeb4bc759f4576dfd6ab87386092d5fd Mon Sep 17 00:00:00 2001 From: "hangyu.tao" Date: Mon, 2 Feb 2026 11:16:34 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E8=B6=8B=E5=8A=BF=E5=88=86=E6=9E=90=E5=9B=BE=E7=9A=84=E6=8C=87?= =?UTF-8?q?=E6=A0=87=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/index.html | 10 ++- frontend/js/main.js | 185 +++++++++++++++++++++----------------------- 2 files changed, 96 insertions(+), 99 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index b233c2b..fd7a66a 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -479,10 +479,16 @@

时间趋势分析

+
diff --git a/frontend/js/main.js b/frontend/js/main.js index 41341f2..388fae5 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -61,7 +61,7 @@ function canDelete() { } document.addEventListener("DOMContentLoaded", function () { - console.log("CRM System Main JS v4.0 Loaded - " + new Date().toLocaleString()); + console.log("CRM System Main JS v4.5 Loaded - " + new Date().toLocaleString()); // 登录守卫 const token = localStorage.getItem("crmToken"); if (!token && !window.location.pathname.endsWith("login.html")) { @@ -1653,7 +1653,9 @@ document.addEventListener("DOMContentLoaded", function () { const ctx = canvas.getContext("2d"); const trendType = - document.getElementById("trendTypeSelect")?.value || "customer"; + document.getElementById("trendTypeSelect")?.value || "all"; + const dateGrain = + document.getElementById("trendChartFieldSelect")?.value || "day"; if (trendChartInstance) { trendChartInstance.destroy(); @@ -1663,11 +1665,23 @@ document.addEventListener("DOMContentLoaded", function () { const dateMap = {}; customers.forEach((customer) => { - const dateStr = normalizeDateValue(customer.intendedProduct); - if (!dateStr) return; + const dateValue = normalizeDateValue(customer.intendedProduct); + if (!dateValue) return; - if (!dateMap[dateStr]) { - dateMap[dateStr] = { + let dateKey = dateValue; + if (dateGrain === "month") { + dateKey = dateValue.substring(0, 7); // YYYY-MM + } else if (dateGrain === "week") { + // Find Monday of that week + const d = new Date(dateValue); + const day = d.getDay(); + const diff = d.getDate() - day + (day === 0 ? -6 : 1); + const monday = new Date(d.setDate(diff)); + dateKey = monday.toISOString().split("T")[0] + " (周)"; + } + + if (!dateMap[dateKey]) { + dateMap[dateKey] = { customers: new Set(), demands: 0, issues: 0, @@ -1676,16 +1690,20 @@ document.addEventListener("DOMContentLoaded", function () { // Count customers if (customer.customerName) { - dateMap[dateStr].customers.add(customer.customerName); + dateMap[dateKey].customers.add(customer.customerName); } // Count demands and issues based on type const type = (customer.type || "").toLowerCase(); if (type.includes("需求")) { - dateMap[dateStr].demands++; + dateMap[dateKey].demands++; } - if (type.includes("问题") || type.includes("功能问题")) { - dateMap[dateStr].issues++; + if ( + type.includes("问题") || + type.includes("功能问题") || + type.includes("反馈") + ) { + dateMap[dateKey].issues++; } }); @@ -1695,96 +1713,60 @@ document.addEventListener("DOMContentLoaded", function () { // Prepare datasets based on selected trend type const datasets = []; + const customerDataset = { + label: "客户数", + data: sortedDates.map((date) => dateMap[date].customers.size), + borderColor: "#FF6B35", + backgroundColor: "rgba(255, 107, 53, 0.1)", + borderWidth: 3, + pointRadius: 5, + pointHoverRadius: 7, + pointBackgroundColor: "#FF6B35", + pointBorderColor: "#fff", + pointBorderWidth: 2, + tension: 0.4, + fill: trendType === "customer", + }; + + const demandDataset = { + label: "需求数", + data: sortedDates.map((date) => dateMap[date].demands), + borderColor: "#4CAF50", + backgroundColor: "rgba(76, 175, 80, 0.1)", + borderWidth: 3, + pointRadius: 5, + pointHoverRadius: 7, + pointBackgroundColor: "#4CAF50", + pointBorderColor: "#fff", + pointBorderWidth: 2, + tension: 0.4, + fill: trendType === "demand", + }; + + const issueDataset = { + label: "反馈数", + data: sortedDates.map((date) => dateMap[date].issues), + borderColor: "#2196F3", + backgroundColor: "rgba(33, 150, 243, 0.1)", + borderWidth: 3, + pointRadius: 5, + pointHoverRadius: 7, + pointBackgroundColor: "#2196F3", + pointBorderColor: "#fff", + pointBorderWidth: 2, + tension: 0.4, + fill: trendType === "issue", + }; + if (trendType === "customer") { - datasets.push({ - label: "客户数", - data: sortedDates.map((date) => dateMap[date].customers.size), - borderColor: "#FF6B35", - backgroundColor: "rgba(255, 107, 53, 0.1)", - borderWidth: 3, - pointRadius: 5, - pointHoverRadius: 7, - pointBackgroundColor: "#FF6B35", - pointBorderColor: "#fff", - pointBorderWidth: 2, - tension: 0.4, - fill: true, - }); + datasets.push(customerDataset); } else if (trendType === "demand") { - datasets.push({ - label: "需求数", - data: sortedDates.map((date) => dateMap[date].demands), - borderColor: "#4CAF50", - backgroundColor: "rgba(76, 175, 80, 0.1)", - borderWidth: 3, - pointRadius: 5, - pointHoverRadius: 7, - pointBackgroundColor: "#4CAF50", - pointBorderColor: "#fff", - pointBorderWidth: 2, - tension: 0.4, - fill: true, - }); + datasets.push(demandDataset); } else if (trendType === "issue") { - datasets.push({ - label: "问题数", - data: sortedDates.map((date) => dateMap[date].issues), - borderColor: "#F28C28", - backgroundColor: "rgba(242, 140, 40, 0.1)", - borderWidth: 3, - pointRadius: 5, - pointHoverRadius: 7, - pointBackgroundColor: "#F28C28", - pointBorderColor: "#fff", - pointBorderWidth: 2, - tension: 0.4, - fill: true, - }); - } else if (trendType === "all") { - datasets.push( - { - label: "客户数", - data: sortedDates.map((date) => dateMap[date].customers.size), - borderColor: "#FF6B35", - backgroundColor: "rgba(255, 107, 53, 0.1)", - borderWidth: 3, - pointRadius: 5, - pointHoverRadius: 7, - pointBackgroundColor: "#FF6B35", - pointBorderColor: "#fff", - pointBorderWidth: 2, - tension: 0.4, - fill: false, - }, - { - label: "需求数", - data: sortedDates.map((date) => dateMap[date].demands), - borderColor: "#4CAF50", - backgroundColor: "rgba(76, 175, 80, 0.1)", - borderWidth: 3, - pointRadius: 5, - pointHoverRadius: 7, - pointBackgroundColor: "#4CAF50", - pointBorderColor: "#fff", - pointBorderWidth: 2, - tension: 0.4, - fill: false, - }, - { - label: "问题数", - data: sortedDates.map((date) => dateMap[date].issues), - borderColor: "#F28C28", - backgroundColor: "rgba(242, 140, 40, 0.1)", - borderWidth: 3, - pointRadius: 5, - pointHoverRadius: 7, - pointBackgroundColor: "#F28C28", - pointBorderColor: "#fff", - pointBorderWidth: 2, - tension: 0.4, - fill: false, - }, - ); + datasets.push(issueDataset); + } else { + // all + datasets.push(customerDataset, demandDataset, issueDataset); } trendChartInstance = new Chart(ctx, { @@ -1928,6 +1910,15 @@ document.addEventListener("DOMContentLoaded", function () { }); } + const trendChartFieldSelect = document.getElementById("trendChartFieldSelect"); + if (trendChartFieldSelect) { + trendChartFieldSelect.addEventListener("change", function () { + const startDate = document.getElementById("startDate").value; + const endDate = document.getElementById("endDate").value; + applyDateFilter(startDate, endDate); + }); + } + // ========== Follow-up Management ========== const followupSection = document.getElementById("followupSection"); const addFollowUpBtn = document.getElementById("addFollowUpBtn");