调整客户统计页面
This commit is contained in:
@@ -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(() => {
|
||||||
|
|||||||
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) {
|
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();
|
||||||
|
|||||||
Reference in New Issue
Block a user