fix:修改时间趋势分析图的指标问题
This commit is contained in:
parent
1134943bb2
commit
a2ad9cafde
@ -479,10 +479,16 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3><i class="fas fa-chart-line"></i> 时间趋势分析</h3>
|
<h3><i class="fas fa-chart-line"></i> 时间趋势分析</h3>
|
||||||
<div class="chart-controls">
|
<div class="chart-controls">
|
||||||
|
<select id="trendTypeSelect" class="chart-field-select">
|
||||||
|
<option value="all" selected>全部指标</option>
|
||||||
|
<option value="customer">客户数</option>
|
||||||
|
<option value="demand">需求数</option>
|
||||||
|
<option value="issue">反馈数</option>
|
||||||
|
</select>
|
||||||
<select id="trendChartFieldSelect" class="chart-field-select">
|
<select id="trendChartFieldSelect" class="chart-field-select">
|
||||||
<option value="month">按月统计</option>
|
<option value="day" selected>按天统计</option>
|
||||||
<option value="week">按周统计</option>
|
<option value="week">按周统计</option>
|
||||||
<option value="day">按天统计</option>
|
<option value="month">按月统计</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -61,7 +61,7 @@ function canDelete() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
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");
|
const token = localStorage.getItem("crmToken");
|
||||||
if (!token && !window.location.pathname.endsWith("login.html")) {
|
if (!token && !window.location.pathname.endsWith("login.html")) {
|
||||||
@ -1653,7 +1653,9 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
|
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
const trendType =
|
const trendType =
|
||||||
document.getElementById("trendTypeSelect")?.value || "customer";
|
document.getElementById("trendTypeSelect")?.value || "all";
|
||||||
|
const dateGrain =
|
||||||
|
document.getElementById("trendChartFieldSelect")?.value || "day";
|
||||||
|
|
||||||
if (trendChartInstance) {
|
if (trendChartInstance) {
|
||||||
trendChartInstance.destroy();
|
trendChartInstance.destroy();
|
||||||
@ -1663,11 +1665,23 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
const dateMap = {};
|
const dateMap = {};
|
||||||
|
|
||||||
customers.forEach((customer) => {
|
customers.forEach((customer) => {
|
||||||
const dateStr = normalizeDateValue(customer.intendedProduct);
|
const dateValue = normalizeDateValue(customer.intendedProduct);
|
||||||
if (!dateStr) return;
|
if (!dateValue) return;
|
||||||
|
|
||||||
if (!dateMap[dateStr]) {
|
let dateKey = dateValue;
|
||||||
dateMap[dateStr] = {
|
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(),
|
customers: new Set(),
|
||||||
demands: 0,
|
demands: 0,
|
||||||
issues: 0,
|
issues: 0,
|
||||||
@ -1676,16 +1690,20 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
|
|
||||||
// Count customers
|
// Count customers
|
||||||
if (customer.customerName) {
|
if (customer.customerName) {
|
||||||
dateMap[dateStr].customers.add(customer.customerName);
|
dateMap[dateKey].customers.add(customer.customerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count demands and issues based on type
|
// Count demands and issues based on type
|
||||||
const type = (customer.type || "").toLowerCase();
|
const type = (customer.type || "").toLowerCase();
|
||||||
if (type.includes("需求")) {
|
if (type.includes("需求")) {
|
||||||
dateMap[dateStr].demands++;
|
dateMap[dateKey].demands++;
|
||||||
}
|
}
|
||||||
if (type.includes("问题") || type.includes("功能问题")) {
|
if (
|
||||||
dateMap[dateStr].issues++;
|
type.includes("问题") ||
|
||||||
|
type.includes("功能问题") ||
|
||||||
|
type.includes("反馈")
|
||||||
|
) {
|
||||||
|
dateMap[dateKey].issues++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1695,96 +1713,60 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
// Prepare datasets based on selected trend type
|
// Prepare datasets based on selected trend type
|
||||||
const datasets = [];
|
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") {
|
if (trendType === "customer") {
|
||||||
datasets.push({
|
datasets.push(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: true,
|
|
||||||
});
|
|
||||||
} else if (trendType === "demand") {
|
} else if (trendType === "demand") {
|
||||||
datasets.push({
|
datasets.push(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: true,
|
|
||||||
});
|
|
||||||
} else if (trendType === "issue") {
|
} else if (trendType === "issue") {
|
||||||
datasets.push({
|
datasets.push(issueDataset);
|
||||||
label: "问题数",
|
} else {
|
||||||
data: sortedDates.map((date) => dateMap[date].issues),
|
// all
|
||||||
borderColor: "#F28C28",
|
datasets.push(customerDataset, demandDataset, issueDataset);
|
||||||
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,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trendChartInstance = new Chart(ctx, {
|
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 ==========
|
// ========== Follow-up Management ==========
|
||||||
const followupSection = document.getElementById("followupSection");
|
const followupSection = document.getElementById("followupSection");
|
||||||
const addFollowUpBtn = document.getElementById("addFollowUpBtn");
|
const addFollowUpBtn = document.getElementById("addFollowUpBtn");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user