From 826f1b2dd09c04f8be0d7269b48f4d181f42c70d Mon Sep 17 00:00:00 2001 From: Timi Date: Wed, 12 Aug 2026 16:24:23 +0800 Subject: [PATCH] update charts --- src/components/EventRecordCalendar.vue | 4 +- src/pages/customer/CustomerDataCharts.vue | 176 +-------------- .../component/CustomerChartSummary.vue | 124 +++++++++++ .../CustomerEventRecordCalendarSection.vue | 104 ++++++++- .../component/CustomerEventStructureChart.vue | 79 ++++++- .../component/CustomerRecordTrendChart.vue | 68 +++++- src/pages/store/StoreDataCharts.vue | 124 +---------- .../store/component/StoreChartSummary.vue | 202 ++++++++++++++++++ .../component/StoreCustomerGenderChart.vue | 16 +- .../component/StoreCustomerGrowthChart.vue | 47 +++- .../StoreEventRecordCalendarSection.vue | 21 +- .../component/StoreEventRecordTrendChart.vue | 85 +++++++- .../component/StoreEventStructureChart.vue | 85 +++++++- src/pages/tabs/SettingTab.vue | 4 +- 14 files changed, 820 insertions(+), 319 deletions(-) create mode 100644 src/pages/customer/component/CustomerChartSummary.vue create mode 100644 src/pages/store/component/StoreChartSummary.vue diff --git a/src/components/EventRecordCalendar.vue b/src/components/EventRecordCalendar.vue index d03d9c9..429bbac 100644 --- a/src/components/EventRecordCalendar.vue +++ b/src/components/EventRecordCalendar.vue @@ -47,7 +47,7 @@
正在加载登记日历
- +
- +
-
- - -
+
import { Time } from "timi-web"; import CustomerAPI from "@/api/CustomerAPI"; -import CustomerChartAPI from "@/api/CustomerChartAPI"; -import EventAPI from "@/api/EventAPI"; import CodeScanner from "@/components/CodeScanner.vue"; import CustomerSelector from "@/components/CustomerSelector.vue"; +import CustomerChartSummary from "@/pages/customer/component/CustomerChartSummary.vue"; import CustomerEventRecordCalendarSection from "@/pages/customer/component/CustomerEventRecordCalendarSection.vue"; import CustomerEventStructureChart from "@/pages/customer/component/CustomerEventStructureChart.vue"; import CustomerRecordTrendChart from "@/pages/customer/component/CustomerRecordTrendChart.vue"; import { useSettingStore } from "@/store/settingStore"; import type { Customer } from "@/types/Customer"; -import type { EventItem } from "@/types/EventItem"; -import type { EventRecord } from "@/types/EventRecord"; -import type { StoreEventRecordCalendarView, StoreEventRecordDailyStatView } from "@/types/Store"; import { permissionCodes } from "@/utils/permission"; -interface SummaryItem { - label: string; - value: string; -} - defineOptions({ name: "CustomerDataCharts" }); @@ -105,56 +94,14 @@ const selectorVisible = ref(false); const scannerVisible = ref(false); const scanStatus = ref("点击扫码开始识别。"); const selectedCustomer = ref(); -const eventList = ref([]); const selectedEventIdList = ref([]); const monthCursor = ref(getMonthStart(new Date())); -const monthRecords = ref([]); -const calendarLoading = ref(false); -const recordDailyStatMap = ref>({}); const chartBeginDate = getDateStart(addMonths(new Date(), -1)); const chartEndDate = getDateEnd(new Date()); const chartDateTextList = buildDateTextList(chartBeginDate, chartEndDate); let latestDecodedText = ""; -let monthDataRequestId = 0; -const eventNameMap = computed(() => { - const map = new Map(); - for (const item of eventList.value) { - if (item.id) { - map.set(item.id, item.name || "未命名事件"); - } - } - return map; -}); -const selectedEventIdSet = computed(() => new Set(selectedEventIdList.value)); -const filteredMonthRecords = computed(() => { - if (!selectedEventIdList.value.length) { - return []; - } - - return monthRecords.value.filter(item => { - if (!item.eventId || !selectedEventIdSet.value.has(item.eventId)) { - return false; - } - const recordDate = Time.toDateObject(item.registeredAt); - return !!recordDate && recordDate.getFullYear() === monthCursor.value.getFullYear() && recordDate.getMonth() === monthCursor.value.getMonth(); - }); -}); const monthDateTextList = computed(() => buildMonthDateTextList(monthCursor.value)); -const summaryList = computed(() => [ - { - label: "本月登记", - value: `${filteredMonthRecords.value.length} 次` - }, - { - label: "转介绍", - value: `${selectedCustomer.value?.invitedCount || 0} 人` - }, - { - label: "最近登记", - value: getRecordEventName(filteredMonthRecords.value[0]) || "暂无" - } -]); watch(routeCustomerCode, (value) => { if (value) { @@ -172,12 +119,7 @@ watch(customerCode, async (value) => { await loadCustomer(value); }); -watch([selectedCustomer, monthCursor], async () => { - await loadMonthData(); -}); - onMounted(async () => { - await loadEvents(); if (routeCustomerId.value) { await loadCustomerById(routeCustomerId.value); } else if (customerCode.value) { @@ -187,11 +129,6 @@ onMounted(async () => { // ---------- 数据 ---------- -async function loadEvents(): Promise { - eventList.value = await EventAPI.listValid(); - selectedEventIdList.value = getEventIdList(); -} - async function loadCustomer(code: string): Promise { const normalizedCode = code.trim(); if (!normalizedCode) { @@ -241,53 +178,6 @@ async function clearCustomerSelection(): Promise { function clearLoadedCustomer(): void { selectedCustomer.value = undefined; selectedCustomerId.value = ""; - monthRecords.value = []; - recordDailyStatMap.value = {}; -} - -async function loadMonthData(): Promise { - const customerId = selectedCustomer.value?.id; - if (!customerId) { - monthRecords.value = []; - recordDailyStatMap.value = {}; - return; - } - - const eventIdList = getEventIdList(); - if (!eventIdList.length) { - monthRecords.value = []; - recordDailyStatMap.value = {}; - return; - } - - const requestId = ++monthDataRequestId; - const calendarBeginDate = getCalendarBeginDate(monthCursor.value); - const calendarEndDate = getDateEnd(addDays(calendarBeginDate, 41)); - calendarLoading.value = true; - try { - const [dailyStatList, calendarRecordList] = await Promise.all([ - CustomerChartAPI.eventRecordDailyStat({ - customerId, - beginAt: Time.toTimestamp(chartBeginDate), - endAt: Time.toTimestamp(chartEndDate), - eventIdList - }), - CustomerChartAPI.eventRecordCalendar({ - customerId, - beginAt: Time.toTimestamp(calendarBeginDate), - endAt: Time.toTimestamp(calendarEndDate), - eventIdList - }) - ]); - if (requestId === monthDataRequestId) { - recordDailyStatMap.value = groupRecordDailyStatByEventId(dailyStatList); - monthRecords.value = calendarRecordList.map(buildCalendarRecord); - } - } finally { - if (requestId === monthDataRequestId) { - calendarLoading.value = false; - } - } } // ---------- 扫码 ---------- @@ -317,48 +207,6 @@ function handleScanStatusChange(value: string): void { scanStatus.value = value; } -// ---------- 统计 ---------- - -function groupRecordDailyStatByEventId(list: StoreEventRecordDailyStatView[]): Record { - const map: Record = {}; - for (const item of list) { - if (!item.eventId) { - continue; - } - if (!map[item.eventId]) { - map[item.eventId] = []; - } - map[item.eventId].push(item); - } - return map; -} - -function getRecordEventName(record?: EventRecord): string { - if (!record) { - return ""; - } - - return record.event?.name || (record.eventId ? eventNameMap.value.get(record.eventId) : "") || "未知事件"; -} - -function getEventIdList(): string[] { - return eventList.value.map(item => item.id).filter((item): item is string => Boolean(item)); -} - -function buildCalendarRecord(record: StoreEventRecordCalendarView): EventRecord { - return { - id: record.id, - customerId: record.customerId, - eventId: record.eventId, - registeredAt: record.registeredAt, - customer: record.customerId || record.customerCode || record.customerName ? { - id: record.customerId, - code: record.customerCode, - name: record.customerName - } : undefined - }; -} - // ---------- 日期 ---------- function getMonthStart(date: Date): Date { @@ -369,11 +217,6 @@ function getDateStart(date: Date): Date { return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0); } -function getCalendarBeginDate(date: Date): Date { - const monthStart = getMonthStart(date); - return addDays(monthStart, -monthStart.getDay()); -} - function buildMonthDateTextList(date: Date): string[] { const monthStart = getMonthStart(date); const nextMonthStart = addMonths(monthStart, 1); @@ -405,6 +248,7 @@ function addMonths(date: Date, months: number): Date { function getDateEnd(date: Date): Date { return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999); } + diff --git a/src/pages/store/component/StoreCustomerGenderChart.vue b/src/pages/store/component/StoreCustomerGenderChart.vue index dcb9bf3..a129b02 100644 --- a/src/pages/store/component/StoreCustomerGenderChart.vue +++ b/src/pages/store/component/StoreCustomerGenderChart.vue @@ -7,12 +7,12 @@ diff --git a/src/pages/store/component/StoreCustomerGrowthChart.vue b/src/pages/store/component/StoreCustomerGrowthChart.vue index a66fce8..50750ac 100644 --- a/src/pages/store/component/StoreCustomerGrowthChart.vue +++ b/src/pages/store/component/StoreCustomerGrowthChart.vue @@ -14,16 +14,24 @@ diff --git a/src/pages/store/component/StoreEventRecordCalendarSection.vue b/src/pages/store/component/StoreEventRecordCalendarSection.vue index d18f83a..b5ddc3e 100644 --- a/src/pages/store/component/StoreEventRecordCalendarSection.vue +++ b/src/pages/store/component/StoreEventRecordCalendarSection.vue @@ -10,6 +10,7 @@