调整客户统计页面

This commit is contained in:
zhonghua.li
2026-02-08 20:01:05 +08:00
parent bcf25432d9
commit 94b0367ac5
3 changed files with 140 additions and 60 deletions

View File

@@ -276,17 +276,26 @@ export default {
}, },
/** /**
* 格式化日期 * 格式化日期
* 支持多种格式Date对象、ISO字符串、YYYY-MM-DD字符串
*/ */
formatDate(dateStr) { formatDate(dateInput) {
if (!dateStr) return ''; if (!dateInput) return '';
try { try {
const date = new Date(dateStr); // 如果已经是 YYYY-MM-DD 格式的字符串,直接返回
if (typeof dateInput === 'string' && /^\d{4}-\d{2}-\d{2}/.test(dateInput)) {
return dateInput.split('T')[0]; // 处理可能带时间的字符串
}
// 如果是 Date 对象或其他格式,转换为 YYYY-MM-DD
const date = new Date(dateInput);
if (isNaN(date.getTime())) {
return String(dateInput);
}
const year = date.getFullYear(); const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
} catch (e) { } catch (e) {
return dateStr; return String(dateInput);
} }
}, },
/** /**
@@ -421,34 +430,50 @@ export default {
return; return;
} }
// 注意salesTotalCustomerCount 是销售人员在所有门店的总客户数所有记录的值都相同) // 累计总客户数所有记录的 countBySales 的总和
// 所以应该使用第一条记录的 salesTotalCustomerCount 作为总客户数,而不是累加 const totalCustomerCount = statisticsList.reduce((sum, item) => {
const firstItem = statisticsList[0]; return sum + (item.countBySales || 0);
const totalCustomerCount = firstItem.salesTotalCustomerCount || firstItem.salesCustomerCount || 0; }, 0);
// 获取今日客户数(如果有今日数据) // 获取今日客户数(如果有今日数据)
// 后端返回的日期是 LocalDate 格式YYYY-MM-DD需要转换为字符串比较
const today = new Date(); const today = new Date();
const todayStr = this.formatDate(today.toISOString()); const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
const todayItem = statisticsList.find(item => {
const itemDate = this.formatDate(item.statisticsDate); // 查找今日的记录(可能有多条,按经销商分组)
return itemDate === todayStr; const todayItems = statisticsList.filter(item => {
// statisticsDate 可能是字符串 "YYYY-MM-DD" 或 Date 对象
let itemDateStr = '';
if (typeof item.statisticsDate === 'string') {
itemDateStr = item.statisticsDate.split('T')[0]; // 处理可能带时间的字符串
} else if (item.statisticsDate) {
itemDateStr = this.formatDate(item.statisticsDate);
}
return itemDateStr === todayStr;
}); });
const todayCustomerCount = todayItem ? (todayItem.salesCustomerCount || 0) : 0;
// 今日客户数是今日所有记录的 countBySales 的总和
const todayCustomerCount = todayItems.reduce((sum, item) => {
return sum + (item.countBySales || 0);
}, 0);
// 构建数据列表(展示每个门店的统计数据) // 构建数据列表(展示每个门店的统计数据)
const formattedList = statisticsList.map(item => { const formattedList = statisticsList.map(item => {
// 使用销售人员接待客户数作为该条记录的客户数 // 使用销售统计的客户数作为该条记录的客户数
const customerCount = item.salesCustomerCount || 0; const customerCount = item.countBySales || 0;
// 格式化日期 // 格式化日期
const date = this.formatDate(item.statisticsDate); let date = '';
if (typeof item.statisticsDate === 'string') {
date = item.statisticsDate.split('T')[0]; // 处理可能带时间的字符串
} else if (item.statisticsDate) {
date = this.formatDate(item.statisticsDate);
}
// 构建描述信息(显示门店名称和日期 // 构建描述信息(显示门店名称)
let description = ''; let description = '';
if (item.dealershipName) { if (item.dealershipName) {
description = `${item.dealershipName}`; description = item.dealershipName;
} else if (item.salesName) {
description = `${item.salesName}的接待`;
} else { } else {
description = '客户接待统计'; description = '客户接待统计';
} }
@@ -503,18 +528,39 @@ export default {
return; return;
} }
// 按日期正序排列(从旧到新,用于图表显示) // 按日期分组,同一天的多个记录(不同经销商)需要合并
const sortedList = [...statisticsList].sort((a, b) => { const dateMap = new Map();
const dateA = new Date(a.statisticsDate); statisticsList.forEach(item => {
const dateB = new Date(b.statisticsDate); // 处理日期格式
return dateA - dateB; let dateStr = '';
if (typeof item.statisticsDate === 'string') {
dateStr = item.statisticsDate.split('T')[0];
} else if (item.statisticsDate) {
dateStr = this.formatDate(item.statisticsDate);
}
if (dateStr) {
const count = item.countBySales || 0;
if (dateMap.has(dateStr)) {
// 如果该日期已存在,累加客户数
dateMap.set(dateStr, dateMap.get(dateStr) + count);
} else {
dateMap.set(dateStr, count);
}
}
}); });
// 提取日期和客户数数据 // 转换为数组并按日期正序排列(从旧到新,用于图表显示)
this.chartData = sortedList.map(item => ({ this.chartData = Array.from(dateMap.entries())
date: item.statisticsDate, .map(([date, count]) => ({
count: item.salesCustomerCount || 0 date: date,
})); count: count
}))
.sort((a, b) => {
const dateA = new Date(a.date);
const dateB = new Date(b.date);
return dateA - dateB;
});
// 延迟绘制确保canvas已渲染 // 延迟绘制确保canvas已渲染
this.$nextTick(() => { this.$nextTick(() => {

View File

@@ -168,18 +168,25 @@ const _sfc_main = {
}, },
/** /**
* 格式化日期 * 格式化日期
* 支持多种格式Date对象、ISO字符串、YYYY-MM-DD字符串
*/ */
formatDate(dateStr) { formatDate(dateInput) {
if (!dateStr) if (!dateInput)
return ""; return "";
try { try {
const date = new Date(dateStr); if (typeof dateInput === "string" && /^\d{4}-\d{2}-\d{2}/.test(dateInput)) {
return dateInput.split("T")[0];
}
const date = new Date(dateInput);
if (isNaN(date.getTime())) {
return String(dateInput);
}
const year = date.getFullYear(); const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0"); const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0"); const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
} catch (e) { } catch (e) {
return dateStr; return String(dateInput);
} }
}, },
/** /**
@@ -215,8 +222,8 @@ const _sfc_main = {
const queryString = Object.keys(queryParams).filter((key) => queryParams[key] !== null && queryParams[key] !== void 0 && queryParams[key] !== "").map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`).join("&"); const queryString = Object.keys(queryParams).filter((key) => queryParams[key] !== null && queryParams[key] !== void 0 && queryParams[key] !== "").map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`).join("&");
const baseUrl = common_config.getApiUrl("/api/customer-statistics/sales"); const baseUrl = common_config.getApiUrl("/api/customer-statistics/sales");
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl; const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:347", "[CustomerCount] 请求参数:", queryParams); common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:356", "[CustomerCount] 请求参数:", queryParams);
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:348", "[CustomerCount] 请求URL:", url); common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:357", "[CustomerCount] 请求URL:", url);
common_vendor.index.showLoading({ common_vendor.index.showLoading({
title: "加载中...", title: "加载中...",
mask: true mask: true
@@ -237,8 +244,8 @@ const _sfc_main = {
return; return;
} }
const statisticsList = result.data || []; const statisticsList = result.data || [];
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:383", "[CustomerCount] 返回数据:", statisticsList); common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:392", "[CustomerCount] 返回数据:", statisticsList);
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:384", "[CustomerCount] 返回结果:", result); common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:393", "[CustomerCount] 返回结果:", result);
this.processStatisticsData(statisticsList); this.processStatisticsData(statisticsList);
common_vendor.index.showToast({ common_vendor.index.showToast({
title: "刷新成功", title: "刷新成功",
@@ -250,7 +257,7 @@ const _sfc_main = {
} }
} catch (error) { } catch (error) {
common_vendor.index.hideLoading(); common_vendor.index.hideLoading();
common_vendor.index.__f__("error", "at pages-subpackage/ai_features/customer_count/customer_count.vue:402", "[CustomerCount] 加载数据失败:", error); common_vendor.index.__f__("error", "at pages-subpackage/ai_features/customer_count/customer_count.vue:411", "[CustomerCount] 加载数据失败:", error);
common_vendor.index.showToast({ common_vendor.index.showToast({
title: error.message || "加载失败,请重试", title: error.message || "加载失败,请重试",
icon: "none", icon: "none",
@@ -270,23 +277,34 @@ const _sfc_main = {
this.dataList = []; this.dataList = [];
return; return;
} }
const firstItem = statisticsList[0]; const totalCustomerCount = statisticsList.reduce((sum, item) => {
const totalCustomerCount = firstItem.salesTotalCustomerCount || firstItem.salesCustomerCount || 0; return sum + (item.countBySales || 0);
}, 0);
const today = /* @__PURE__ */ new Date(); const today = /* @__PURE__ */ new Date();
const todayStr = this.formatDate(today.toISOString()); const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(today.getDate()).padStart(2, "0")}`;
const todayItem = statisticsList.find((item) => { const todayItems = statisticsList.filter((item) => {
const itemDate = this.formatDate(item.statisticsDate); let itemDateStr = "";
return itemDate === todayStr; if (typeof item.statisticsDate === "string") {
itemDateStr = item.statisticsDate.split("T")[0];
} else if (item.statisticsDate) {
itemDateStr = this.formatDate(item.statisticsDate);
}
return itemDateStr === todayStr;
}); });
const todayCustomerCount = todayItem ? todayItem.salesCustomerCount || 0 : 0; const todayCustomerCount = todayItems.reduce((sum, item) => {
return sum + (item.countBySales || 0);
}, 0);
const formattedList = statisticsList.map((item) => { const formattedList = statisticsList.map((item) => {
const customerCount = item.salesCustomerCount || 0; const customerCount = item.countBySales || 0;
const date = this.formatDate(item.statisticsDate); let date = "";
if (typeof item.statisticsDate === "string") {
date = item.statisticsDate.split("T")[0];
} else if (item.statisticsDate) {
date = this.formatDate(item.statisticsDate);
}
let description = ""; let description = "";
if (item.dealershipName) { if (item.dealershipName) {
description = `${item.dealershipName}`; description = item.dealershipName;
} else if (item.salesName) {
description = `${item.salesName}的接待`;
} else { } else {
description = "客户接待统计"; description = "客户接待统计";
} }
@@ -308,7 +326,7 @@ const _sfc_main = {
this.totalCustomers = this.formatCustomerCount(totalCustomerCount); this.totalCustomers = this.formatCustomerCount(totalCustomerCount);
this.todayCustomers = this.formatCustomerCount(todayCustomerCount); this.todayCustomers = this.formatCustomerCount(todayCustomerCount);
this.dataList = formattedList; this.dataList = formattedList;
common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:477", "[CustomerCount] 数据处理完成:", { common_vendor.index.__f__("log", "at pages-subpackage/ai_features/customer_count/customer_count.vue:502", "[CustomerCount] 数据处理完成:", {
totalCustomers: this.totalCustomers, totalCustomers: this.totalCustomers,
todayCustomers: this.todayCustomers, todayCustomers: this.todayCustomers,
dataListCount: this.dataList.length, dataListCount: this.dataList.length,
@@ -332,15 +350,31 @@ const _sfc_main = {
this.chartData = []; this.chartData = [];
return; return;
} }
const sortedList = [...statisticsList].sort((a, b) => { const dateMap = /* @__PURE__ */ new Map();
const dateA = new Date(a.statisticsDate); statisticsList.forEach((item) => {
const dateB = new Date(b.statisticsDate); let dateStr = "";
if (typeof item.statisticsDate === "string") {
dateStr = item.statisticsDate.split("T")[0];
} else if (item.statisticsDate) {
dateStr = this.formatDate(item.statisticsDate);
}
if (dateStr) {
const count = item.countBySales || 0;
if (dateMap.has(dateStr)) {
dateMap.set(dateStr, dateMap.get(dateStr) + count);
} else {
dateMap.set(dateStr, count);
}
}
});
this.chartData = Array.from(dateMap.entries()).map(([date, count]) => ({
date,
count
})).sort((a, b) => {
const dateA = new Date(a.date);
const dateB = new Date(b.date);
return dateA - dateB; return dateA - dateB;
}); });
this.chartData = sortedList.map((item) => ({
date: item.statisticsDate,
count: item.salesCustomerCount || 0
}));
this.$nextTick(() => { this.$nextTick(() => {
setTimeout(() => { setTimeout(() => {
this.drawChart(); this.drawChart();