add customer list for StoreCustomerGrowthChart.vue
This commit is contained in:
@@ -15,16 +15,18 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Time } from "timi-web";
|
import { Time } from "timi-web";
|
||||||
import type { EChartsOption } from "echarts";
|
import type { DefaultLabelFormatterCallbackParams, EChartsOption } from "echarts";
|
||||||
import StoreChartAPI from "@/api/StoreChartAPI";
|
import StoreChartAPI from "@/api/StoreChartAPI";
|
||||||
import ChartRangeSlider from "@/components/ChartRangeSlider.vue";
|
import ChartRangeSlider from "@/components/ChartRangeSlider.vue";
|
||||||
import type { CustomerDailyStatView } from "@/types/Customer";
|
import type { CustomerDailyStatCustomerView, CustomerDailyStatView } from "@/types/Customer";
|
||||||
import { buildStoreBaseChartOption, useStoreChart, useStoreChartWindow } from "@/pages/store/component/useStoreChart";
|
import { buildStoreBaseChartOption, useStoreChart, useStoreChartWindow } from "@/pages/store/component/useStoreChart";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
dateTextList: string[];
|
dateTextList: string[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const MAX_TOOLTIP_CUSTOMER_COUNT = 24;
|
||||||
|
|
||||||
// ---------- 图表数据 ----------
|
// ---------- 图表数据 ----------
|
||||||
|
|
||||||
const statList = ref<CustomerDailyStatView[]>([]);
|
const statList = ref<CustomerDailyStatView[]>([]);
|
||||||
@@ -82,7 +84,12 @@ const chartOption = computed<EChartsOption>(() => ({
|
|||||||
yAxisIndex: 1,
|
yAxisIndex: 1,
|
||||||
data: visibleDateTextList.value.map(dateText => getDailyStat(dateText)?.newCustomerCount || 0)
|
data: visibleDateTextList.value.map(dateText => getDailyStat(dateText)?.newCustomerCount || 0)
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis",
|
||||||
|
formatter: params => formatGrowthTooltip(params),
|
||||||
|
extraCssText: "max-width: min(19rem, calc(100vw - 2rem));"
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { chartElement } = useStoreChart(chartOption);
|
const { chartElement } = useStoreChart(chartOption);
|
||||||
@@ -115,6 +122,45 @@ function getDailyStat(dateText: string): CustomerDailyStatView | undefined {
|
|||||||
return statList.value.find(item => item.dateValue === dateValue);
|
return statList.value.find(item => item.dateValue === dateValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatGrowthTooltip(params: DefaultLabelFormatterCallbackParams | DefaultLabelFormatterCallbackParams[]): string {
|
||||||
|
const firstParam = Array.isArray(params) ? params[0] : params;
|
||||||
|
const dateText = visibleDateTextList.value[firstParam?.dataIndex ?? -1];
|
||||||
|
const stat = dateText ? getDailyStat(dateText) : undefined;
|
||||||
|
if (!dateText || !stat) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const customerList = stat.customerList || [];
|
||||||
|
const visibleCustomerList = customerList.slice(0, MAX_TOOLTIP_CUSTOMER_COUNT);
|
||||||
|
const customerHTML = visibleCustomerList.length
|
||||||
|
? visibleCustomerList.map(formatCustomerTooltipItem).join("")
|
||||||
|
: "";
|
||||||
|
const hiddenCustomerCount = Math.max(0, customerList.length - visibleCustomerList.length);
|
||||||
|
const hiddenCustomerHTML = hiddenCustomerCount
|
||||||
|
? `<div style="color:#94a3b8;margin-top:4px;">还有 ${hiddenCustomerCount} 人未显示</div>`
|
||||||
|
: "";
|
||||||
|
return [
|
||||||
|
`<div style="font-weight:700;margin-bottom:6px;">${escapeTooltipHTML(dateText)}</div>`,
|
||||||
|
`<div>客户总量:${stat.totalCustomerCount || 0} 人</div>`,
|
||||||
|
`<div>新客户量:${stat.newCustomerCount || 0} 人</div>`,
|
||||||
|
`<div style="display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px 10px;margin-top:6px;">${customerHTML}${hiddenCustomerHTML}</div>`
|
||||||
|
].join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCustomerTooltipItem(customer: CustomerDailyStatCustomerView): string {
|
||||||
|
return `<div style="line-height:1.6;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${escapeTooltipHTML(customer.name || "未命名客户")}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeTooltipHTML(value: string): string {
|
||||||
|
return value.replace(/[&<>"']/g, character => ({
|
||||||
|
"&": "&",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
"\"": """,
|
||||||
|
"'": "'"
|
||||||
|
}[character] || character));
|
||||||
|
}
|
||||||
|
|
||||||
// ---------- 日期 ----------
|
// ---------- 日期 ----------
|
||||||
|
|
||||||
function getDateStart(dateText: string): Date {
|
function getDateStart(dateText: string): Date {
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ export type CustomerDailyStatView = {
|
|||||||
dateValue?: number;
|
dateValue?: number;
|
||||||
newCustomerCount?: number;
|
newCustomerCount?: number;
|
||||||
totalCustomerCount?: number;
|
totalCustomerCount?: number;
|
||||||
|
customerList?: CustomerDailyStatCustomerView[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CustomerDailyStatCustomerView = {
|
||||||
|
name?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CustomerGenderStatView = {
|
export type CustomerGenderStatView = {
|
||||||
|
|||||||
Reference in New Issue
Block a user