调整客户统计页面
This commit is contained in:
@@ -276,17 +276,26 @@ export default {
|
||||
},
|
||||
/**
|
||||
* 格式化日期
|
||||
* 支持多种格式:Date对象、ISO字符串、YYYY-MM-DD字符串
|
||||
*/
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
formatDate(dateInput) {
|
||||
if (!dateInput) return '';
|
||||
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 month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
} catch (e) {
|
||||
return dateStr;
|
||||
return String(dateInput);
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -421,34 +430,50 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
// 注意:salesTotalCustomerCount 是销售人员在所有门店的总客户数(所有记录的值都相同)
|
||||
// 所以应该使用第一条记录的 salesTotalCustomerCount 作为总客户数,而不是累加
|
||||
const firstItem = statisticsList[0];
|
||||
const totalCustomerCount = firstItem.salesTotalCustomerCount || firstItem.salesCustomerCount || 0;
|
||||
// 累计总客户数:所有记录的 countBySales 的总和
|
||||
const totalCustomerCount = statisticsList.reduce((sum, item) => {
|
||||
return sum + (item.countBySales || 0);
|
||||
}, 0);
|
||||
|
||||
// 获取今日客户数(如果有今日数据)
|
||||
// 后端返回的日期是 LocalDate 格式(YYYY-MM-DD),需要转换为字符串比较
|
||||
const today = new Date();
|
||||
const todayStr = this.formatDate(today.toISOString());
|
||||
const todayItem = statisticsList.find(item => {
|
||||
const itemDate = this.formatDate(item.statisticsDate);
|
||||
return itemDate === todayStr;
|
||||
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
|
||||
|
||||
// 查找今日的记录(可能有多条,按经销商分组)
|
||||
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 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 = '';
|
||||
if (item.dealershipName) {
|
||||
description = `${item.dealershipName}`;
|
||||
} else if (item.salesName) {
|
||||
description = `${item.salesName}的接待`;
|
||||
description = item.dealershipName;
|
||||
} else {
|
||||
description = '客户接待统计';
|
||||
}
|
||||
@@ -503,18 +528,39 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
// 按日期正序排列(从旧到新,用于图表显示)
|
||||
const sortedList = [...statisticsList].sort((a, b) => {
|
||||
const dateA = new Date(a.statisticsDate);
|
||||
const dateB = new Date(b.statisticsDate);
|
||||
return dateA - dateB;
|
||||
// 按日期分组,同一天的多个记录(不同经销商)需要合并
|
||||
const dateMap = new Map();
|
||||
statisticsList.forEach(item => {
|
||||
// 处理日期格式
|
||||
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 => ({
|
||||
date: item.statisticsDate,
|
||||
count: item.salesCustomerCount || 0
|
||||
}));
|
||||
// 转换为数组并按日期正序排列(从旧到新,用于图表显示)
|
||||
this.chartData = Array.from(dateMap.entries())
|
||||
.map(([date, count]) => ({
|
||||
date: date,
|
||||
count: count
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
const dateA = new Date(a.date);
|
||||
const dateB = new Date(b.date);
|
||||
return dateA - dateB;
|
||||
});
|
||||
|
||||
// 延迟绘制,确保canvas已渲染
|
||||
this.$nextTick(() => {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -168,18 +168,25 @@ const _sfc_main = {
|
||||
},
|
||||
/**
|
||||
* 格式化日期
|
||||
* 支持多种格式:Date对象、ISO字符串、YYYY-MM-DD字符串
|
||||
*/
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr)
|
||||
formatDate(dateInput) {
|
||||
if (!dateInput)
|
||||
return "";
|
||||
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 month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
} 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 baseUrl = common_config.getApiUrl("/api/customer-statistics/sales");
|
||||
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:348", "[CustomerCount] 请求URL:", url);
|
||||
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:357", "[CustomerCount] 请求URL:", url);
|
||||
common_vendor.index.showLoading({
|
||||
title: "加载中...",
|
||||
mask: true
|
||||
@@ -237,8 +244,8 @@ const _sfc_main = {
|
||||
return;
|
||||
}
|
||||
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:384", "[CustomerCount] 返回结果:", result);
|
||||
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:393", "[CustomerCount] 返回结果:", result);
|
||||
this.processStatisticsData(statisticsList);
|
||||
common_vendor.index.showToast({
|
||||
title: "刷新成功",
|
||||
@@ -250,7 +257,7 @@ const _sfc_main = {
|
||||
}
|
||||
} catch (error) {
|
||||
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({
|
||||
title: error.message || "加载失败,请重试",
|
||||
icon: "none",
|
||||
@@ -270,23 +277,34 @@ const _sfc_main = {
|
||||
this.dataList = [];
|
||||
return;
|
||||
}
|
||||
const firstItem = statisticsList[0];
|
||||
const totalCustomerCount = firstItem.salesTotalCustomerCount || firstItem.salesCustomerCount || 0;
|
||||
const totalCustomerCount = statisticsList.reduce((sum, item) => {
|
||||
return sum + (item.countBySales || 0);
|
||||
}, 0);
|
||||
const today = /* @__PURE__ */ new Date();
|
||||
const todayStr = this.formatDate(today.toISOString());
|
||||
const todayItem = statisticsList.find((item) => {
|
||||
const itemDate = this.formatDate(item.statisticsDate);
|
||||
return itemDate === todayStr;
|
||||
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-${String(today.getDate()).padStart(2, "0")}`;
|
||||
const todayItems = statisticsList.filter((item) => {
|
||||
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;
|
||||
const todayCustomerCount = todayItems.reduce((sum, item) => {
|
||||
return sum + (item.countBySales || 0);
|
||||
}, 0);
|
||||
const formattedList = statisticsList.map((item) => {
|
||||
const customerCount = item.salesCustomerCount || 0;
|
||||
const date = this.formatDate(item.statisticsDate);
|
||||
const customerCount = item.countBySales || 0;
|
||||
let date = "";
|
||||
if (typeof item.statisticsDate === "string") {
|
||||
date = item.statisticsDate.split("T")[0];
|
||||
} else if (item.statisticsDate) {
|
||||
date = this.formatDate(item.statisticsDate);
|
||||
}
|
||||
let description = "";
|
||||
if (item.dealershipName) {
|
||||
description = `${item.dealershipName}`;
|
||||
} else if (item.salesName) {
|
||||
description = `${item.salesName}的接待`;
|
||||
description = item.dealershipName;
|
||||
} else {
|
||||
description = "客户接待统计";
|
||||
}
|
||||
@@ -308,7 +326,7 @@ const _sfc_main = {
|
||||
this.totalCustomers = this.formatCustomerCount(totalCustomerCount);
|
||||
this.todayCustomers = this.formatCustomerCount(todayCustomerCount);
|
||||
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,
|
||||
todayCustomers: this.todayCustomers,
|
||||
dataListCount: this.dataList.length,
|
||||
@@ -332,15 +350,31 @@ const _sfc_main = {
|
||||
this.chartData = [];
|
||||
return;
|
||||
}
|
||||
const sortedList = [...statisticsList].sort((a, b) => {
|
||||
const dateA = new Date(a.statisticsDate);
|
||||
const dateB = new Date(b.statisticsDate);
|
||||
const dateMap = /* @__PURE__ */ new Map();
|
||||
statisticsList.forEach((item) => {
|
||||
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;
|
||||
});
|
||||
this.chartData = sortedList.map((item) => ({
|
||||
date: item.statisticsDate,
|
||||
count: item.salesCustomerCount || 0
|
||||
}));
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.drawChart();
|
||||
|
||||
Reference in New Issue
Block a user