217 lines
5.6 KiB
Vue
217 lines
5.6 KiB
Vue
<template>
|
|
<section class="order-charts">
|
|
<order-daily-chart
|
|
:date-text-list="dateTextList"
|
|
:list="dailyList"
|
|
:loading="isLoading"
|
|
/>
|
|
<div class="two-columns">
|
|
<customer-order-product-rank-chart
|
|
:list="productRankList"
|
|
:loading="isLoading"
|
|
/>
|
|
<customer-order-sku-rank-chart
|
|
:list="skuRankList"
|
|
:loading="isLoading"
|
|
/>
|
|
</div>
|
|
<customer-consumption-daily-chart
|
|
:date-text-list="dateTextList"
|
|
:list="consumptionDailyList"
|
|
:loading="isLoading"
|
|
/>
|
|
<customer-order-calendar-chart
|
|
:date-text-list="dateTextList"
|
|
:list="calendarList"
|
|
:loading="isLoading"
|
|
/>
|
|
<div class="two-columns">
|
|
<customer-repeat-daily-chart
|
|
:date-text-list="dateTextList"
|
|
:list="repeatDailyList"
|
|
:loading="isLoading"
|
|
/>
|
|
<customer-repeat-interval-chart
|
|
:list="repeatIntervalList"
|
|
:loading="isLoading"
|
|
/>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import GaoSalesOrderChartAPI from "@/api/GaoSalesOrderChartAPI";
|
|
import CustomerConsumptionDailyChart from "@/pages/customer/component/CustomerConsumptionDailyChart.vue";
|
|
import CustomerOrderCalendarChart from "@/pages/customer/component/CustomerOrderCalendarChart.vue";
|
|
import CustomerOrderProductRankChart from "@/pages/customer/component/CustomerOrderProductRankChart.vue";
|
|
import CustomerOrderSkuRankChart from "@/pages/customer/component/CustomerOrderSkuRankChart.vue";
|
|
import CustomerRepeatDailyChart from "@/pages/customer/component/CustomerRepeatDailyChart.vue";
|
|
import CustomerRepeatIntervalChart from "@/pages/customer/component/CustomerRepeatIntervalChart.vue";
|
|
import OrderDailyChart from "@/pages/product/component/OrderDailyChart.vue";
|
|
import type {
|
|
GaoCustomerOrderProductRankView,
|
|
GaoCustomerOrderSkuRankView,
|
|
GaoCustomerRepeatDailyStatView,
|
|
GaoCustomerRepeatIntervalStatView,
|
|
GaoSalesOrderCalendarStatView,
|
|
GaoSalesOrderConsumptionDailyStatView,
|
|
GaoSalesOrderDailyStatView
|
|
} from "@/types/GaoChart";
|
|
import { getErrorMessage } from "@/utils/error";
|
|
import { Message } from "@/utils/message";
|
|
|
|
defineOptions({
|
|
name: "CustomerOrderCharts"
|
|
});
|
|
|
|
const props = defineProps<{
|
|
customerId: string;
|
|
dateTextList: string[];
|
|
storeId?: string;
|
|
}>();
|
|
|
|
const dailyList = ref<GaoSalesOrderDailyStatView[]>([]);
|
|
const productRankList = ref<GaoCustomerOrderProductRankView[]>([]);
|
|
const skuRankList = ref<GaoCustomerOrderSkuRankView[]>([]);
|
|
const consumptionDailyList = ref<GaoSalesOrderConsumptionDailyStatView[]>([]);
|
|
const calendarList = ref<GaoSalesOrderCalendarStatView[]>([]);
|
|
const repeatDailyList = ref<GaoCustomerRepeatDailyStatView[]>([]);
|
|
const repeatIntervalList = ref<GaoCustomerRepeatIntervalStatView[]>([]);
|
|
const isLoading = ref(false);
|
|
let requestId = 0;
|
|
|
|
watch([
|
|
() => props.customerId,
|
|
() => props.storeId,
|
|
() => props.dateTextList
|
|
], async () => {
|
|
await loadCharts();
|
|
}, {
|
|
deep: true,
|
|
immediate: true
|
|
});
|
|
|
|
async function loadCharts(): Promise<void> {
|
|
if (!props.customerId || !props.dateTextList.length) {
|
|
clearData();
|
|
return;
|
|
}
|
|
|
|
const currentRequestId = ++requestId;
|
|
isLoading.value = true;
|
|
try {
|
|
const request = {
|
|
storeId: props.storeId,
|
|
customerId: props.customerId,
|
|
beginAt: getDateStart(props.dateTextList[0]),
|
|
endAt: getDateEnd(props.dateTextList[props.dateTextList.length - 1]),
|
|
topN: 10
|
|
};
|
|
const [daily, productRank, skuRank, consumptionDaily, calendar, repeatDaily, repeatInterval] = await Promise.all([
|
|
GaoSalesOrderChartAPI.daily(request),
|
|
GaoSalesOrderChartAPI.customerProductRank(request),
|
|
GaoSalesOrderChartAPI.customerSkuRank(request),
|
|
GaoSalesOrderChartAPI.consumptionDaily(request),
|
|
GaoSalesOrderChartAPI.calendar(request),
|
|
GaoSalesOrderChartAPI.repeatDaily(request),
|
|
GaoSalesOrderChartAPI.repeatInterval(request)
|
|
]);
|
|
if (currentRequestId !== requestId) {
|
|
return;
|
|
}
|
|
dailyList.value = daily || [];
|
|
productRankList.value = productRank || [];
|
|
skuRankList.value = skuRank || [];
|
|
consumptionDailyList.value = consumptionDaily || [];
|
|
calendarList.value = calendar || [];
|
|
repeatDailyList.value = repeatDaily || [];
|
|
repeatIntervalList.value = repeatInterval || [];
|
|
} catch (error) {
|
|
if (currentRequestId === requestId) {
|
|
Message.error(getErrorMessage(error, "客户订单图表加载失败"));
|
|
}
|
|
} finally {
|
|
if (currentRequestId === requestId) {
|
|
isLoading.value = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
function clearData(): void {
|
|
isLoading.value = false;
|
|
dailyList.value = [];
|
|
productRankList.value = [];
|
|
skuRankList.value = [];
|
|
consumptionDailyList.value = [];
|
|
calendarList.value = [];
|
|
repeatDailyList.value = [];
|
|
repeatIntervalList.value = [];
|
|
}
|
|
|
|
function getDateStart(dateText: string): number {
|
|
const [year, month, day] = dateText.split("-").map(Number);
|
|
return new Date(year, month - 1, day, 0, 0, 0, 0).getTime();
|
|
}
|
|
|
|
function getDateEnd(dateText: string): number {
|
|
const [year, month, day] = dateText.split("-").map(Number);
|
|
return new Date(year, month - 1, day, 23, 59, 59, 999).getTime();
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.order-charts {
|
|
gap: 1rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.section-heading {
|
|
gap: .5rem;
|
|
padding: 0 .25rem;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.eyebrow {
|
|
color: var(--td-brand-color);
|
|
font-size: .6875rem;
|
|
font-weight: 700;
|
|
letter-spacing: .12em;
|
|
}
|
|
|
|
h2 {
|
|
color: #0f172a;
|
|
margin: .25rem 0 0;
|
|
font-size: 1.125rem;
|
|
}
|
|
|
|
.section-heading > span {
|
|
color: #94a3b8;
|
|
font-size: .6875rem;
|
|
}
|
|
|
|
.two-columns {
|
|
gap: 1rem;
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
}
|
|
|
|
:global(html.theme-dark) {
|
|
.order-charts {
|
|
h2 {
|
|
color: #e2e8f0;
|
|
}
|
|
}
|
|
}
|
|
|
|
@media (max-width: 42rem) {
|
|
.order-charts {
|
|
.two-columns {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
}
|
|
</style>
|