mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-16 07:57:33 +08:00
add overview sankey chart for categorical analysis on desktop version
This commit is contained in:
@@ -14,6 +14,7 @@ import { StatisticsAnalysisType, ChartDataType, ChartSortingType, ChartDateAggre
|
||||
import { DISPLAY_HIDDEN_AMOUNT } from '@/consts/numeral.ts';
|
||||
|
||||
import type {
|
||||
TransactionStatisticResponseWithInfo,
|
||||
TransactionCategoricalAnalysisData,
|
||||
TransactionCategoricalAnalysisDataItem,
|
||||
TransactionTrendsAnalysisData
|
||||
@@ -230,6 +231,7 @@ export function useStatisticsTransactionPageBase() {
|
||||
});
|
||||
|
||||
const categoricalAnalysisData = computed<TransactionCategoricalAnalysisData>(() => statisticsStore.categoricalAnalysisData);
|
||||
const categoricalAllAnalysisData = computed<TransactionStatisticResponseWithInfo | null>(() => statisticsStore.categoricalAllAnalysisData);
|
||||
const trendsAnalysisData = computed<TransactionTrendsAnalysisData | null>(() => statisticsStore.trendsAnalysisData);
|
||||
|
||||
function canShowCustomDateRange(dateRangeType: number): boolean {
|
||||
@@ -301,6 +303,7 @@ export function useStatisticsTransactionPageBase() {
|
||||
showTotalAmountInTrendsChart,
|
||||
translateNameInTrendsChart,
|
||||
categoricalAnalysisData,
|
||||
categoricalAllAnalysisData,
|
||||
trendsAnalysisData,
|
||||
// functions
|
||||
canShowCustomDateRange,
|
||||
|
||||
@@ -21,6 +21,17 @@
|
||||
:disabled="loading"
|
||||
:items="allChartTypes"
|
||||
v-model="queryChartType"
|
||||
v-show="!isQuerySpecialChartType"
|
||||
/>
|
||||
<v-select
|
||||
item-title="displayName"
|
||||
item-value="type"
|
||||
class="mt-2"
|
||||
density="compact"
|
||||
:disabled="true"
|
||||
:items="[{ displayName: tt('Sankey Chart'), type: 0 }]"
|
||||
:model-value="0"
|
||||
v-show="isQuerySpecialChartType && queryChartDataType === ChartDataType.Overview.type"
|
||||
/>
|
||||
</div>
|
||||
<div class="mx-6 mt-4">
|
||||
@@ -38,7 +49,7 @@
|
||||
<v-tabs show-arrows class="my-4" direction="vertical"
|
||||
:disabled="loading" v-model="queryChartDataType">
|
||||
<v-tab class="tab-text-truncate" :key="dataType.type" :value="dataType.type"
|
||||
v-for="dataType in ChartDataType.values()"
|
||||
v-for="dataType in ChartDataType.values(undefined, true)"
|
||||
v-show="dataType.isAvailableAnalysisType(queryAnalysisType)">
|
||||
<span class="text-truncate">{{ tt(dataType.name) }}</span>
|
||||
<v-tooltip activator="parent" location="right">{{ tt(dataType.name) }}</v-tooltip>
|
||||
@@ -48,7 +59,7 @@
|
||||
<v-main>
|
||||
<v-window class="d-flex flex-grow-1 disable-tab-transition w-100-window-container" v-model="activeTab">
|
||||
<v-window-item value="statisticsPage">
|
||||
<v-card variant="flat" :min-height="queryAnalysisType === StatisticsAnalysisType.TrendAnalysis ? '860' : '700'">
|
||||
<v-card variant="flat" :min-height="queryAnalysisType === StatisticsAnalysisType.TrendAnalysis ? '860' : '760'">
|
||||
<template #title>
|
||||
<div class="title-and-toolbar d-flex align-center">
|
||||
<v-btn class="me-3 d-md-none" density="compact" color="default" variant="plain"
|
||||
@@ -160,7 +171,7 @@
|
||||
</template>
|
||||
|
||||
<v-card-text class="statistics-overview-title pt-0" :class="{ 'disabled': loading }"
|
||||
v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && (initing || (categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length))">
|
||||
v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && !isQuerySpecialChartType && (initing || (categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length))">
|
||||
<span class="statistics-subtitle">{{ totalAmountName }}</span>
|
||||
<span class="statistics-overview-amount ms-3"
|
||||
:class="statisticsTextColor"
|
||||
@@ -173,12 +184,29 @@
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text class="statistics-overview-title pt-0"
|
||||
v-else-if="!initing && ((queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && (!categoricalAnalysisData || !categoricalAnalysisData.items || !categoricalAnalysisData.items.length))
|
||||
v-else-if="!initing && ((queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && !isQuerySpecialChartType && (!categoricalAnalysisData || !categoricalAnalysisData.items || !categoricalAnalysisData.items.length))
|
||||
|| (queryAnalysisType === StatisticsAnalysisType.TrendAnalysis && (!trendsAnalysisData || !trendsAnalysisData.items || !trendsAnalysisData.items.length)))">
|
||||
<span class="statistics-subtitle statistics-overview-empty-tip">{{ tt('No transaction data') }}</span>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && query.categoricalChartType === CategoricalChartType.Pie.type">
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && queryChartDataType === ChartDataType.Overview.type">
|
||||
<account-and-category-sankey-chart
|
||||
:items="[]"
|
||||
:sorting-type="querySortingType"
|
||||
:skeleton="true"
|
||||
v-if="initing"
|
||||
/>
|
||||
<account-and-category-sankey-chart
|
||||
:items="categoricalAllAnalysisData && categoricalAllAnalysisData.items && categoricalAllAnalysisData.items.length ? categoricalAllAnalysisData.items : []"
|
||||
:sorting-type="querySortingType"
|
||||
:enable-click-item="true"
|
||||
:default-currency="defaultCurrency"
|
||||
v-else-if="!initing"
|
||||
@click="onClickSankeyChartItem"
|
||||
/>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && !isQuerySpecialChartType && query.categoricalChartType === CategoricalChartType.Pie.type">
|
||||
<pie-chart
|
||||
:items="[
|
||||
{id: '1', name: '---', value: 60, color: '7c7c7f'},
|
||||
@@ -191,7 +219,7 @@
|
||||
value-field="value"
|
||||
color-field="color"
|
||||
v-if="initing"
|
||||
></pie-chart>
|
||||
/>
|
||||
<pie-chart
|
||||
:items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
|
||||
:min-valid-percent="0.0001"
|
||||
@@ -208,7 +236,7 @@
|
||||
/>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && query.categoricalChartType === CategoricalChartType.Bar.type">
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && !isQuerySpecialChartType && query.categoricalChartType === CategoricalChartType.Bar.type">
|
||||
<v-list rounded lines="two" v-if="initing">
|
||||
<template :key="itemIdx" v-for="itemIdx in [ 1, 2, 3 ]">
|
||||
<v-list-item class="ps-0">
|
||||
@@ -263,7 +291,7 @@
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && query.categoricalChartType === CategoricalChartType.Radar.type">
|
||||
<v-card-text :class="{ 'readonly': loading }" v-if="queryAnalysisType === StatisticsAnalysisType.CategoricalAnalysis && !isQuerySpecialChartType && query.categoricalChartType === CategoricalChartType.Radar.type">
|
||||
<radar-chart
|
||||
:items="[
|
||||
{name: '---', value: 10},
|
||||
@@ -277,7 +305,7 @@
|
||||
name-field="name"
|
||||
value-field="value"
|
||||
v-if="initing"
|
||||
></radar-chart>
|
||||
/>
|
||||
<radar-chart
|
||||
:items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
|
||||
:min-valid-percent="0.0001"
|
||||
@@ -493,6 +521,7 @@ const {
|
||||
showTotalAmountInTrendsChart,
|
||||
translateNameInTrendsChart,
|
||||
categoricalAnalysisData,
|
||||
categoricalAllAnalysisData,
|
||||
trendsAnalysisData,
|
||||
canShowCustomDateRange,
|
||||
getTransactionCategoricalAnalysisDataItemDisplayColor,
|
||||
@@ -576,6 +605,10 @@ const querySortingType = computed<number>({
|
||||
}
|
||||
});
|
||||
|
||||
const isQuerySpecialChartType = computed<boolean>(() => {
|
||||
return ChartDataType.valueOf(queryChartDataType.value)?.specialChart ?? false;
|
||||
});
|
||||
|
||||
const statisticsTextColor = computed<string>(() => {
|
||||
if (query.value.chartDataType === ChartDataType.OutflowsByAccount.type ||
|
||||
query.value.chartDataType === ChartDataType.ExpenseByAccount.type ||
|
||||
@@ -705,7 +738,8 @@ function reload(force: boolean): Promise<unknown> | null {
|
||||
|
||||
loading.value = true;
|
||||
|
||||
if (query.value.chartDataType === ChartDataType.OutflowsByAccount.type ||
|
||||
if (query.value.chartDataType === ChartDataType.Overview.type ||
|
||||
query.value.chartDataType === ChartDataType.OutflowsByAccount.type ||
|
||||
query.value.chartDataType === ChartDataType.ExpenseByAccount.type ||
|
||||
query.value.chartDataType === ChartDataType.ExpenseByPrimaryCategory.type ||
|
||||
query.value.chartDataType === ChartDataType.ExpenseBySecondaryCategory.type ||
|
||||
@@ -1019,6 +1053,23 @@ function exportResults(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function onClickSankeyChartItem(sourceItemType: 'account' | 'category', sourceItemId: string, targetItemType?: 'account' | 'category', targetItemId?: string): void {
|
||||
if (sourceItemType === 'category' && targetItemType === 'category' && sourceItemId && targetItemId) {
|
||||
const sourceCategory = transactionCategoriesStore.allTransactionCategoriesMap[sourceItemId];
|
||||
const targetCategory = transactionCategoriesStore.allTransactionCategoriesMap[targetItemId];
|
||||
|
||||
if (sourceCategory?.parentId === targetCategory?.id) {
|
||||
router.push(getTransactionItemLinkUrl(`${sourceItemType}:${sourceItemId}`));
|
||||
return;
|
||||
} else if (targetCategory?.parentId === sourceCategory?.id) {
|
||||
router.push(getTransactionItemLinkUrl(`${targetItemType}:${targetItemId}`));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
router.push(getTransactionItemLinkUrl(`${sourceItemType}:${sourceItemId}` + (targetItemType && targetItemId ? `-${targetItemType}:${targetItemId}` : '')));
|
||||
}
|
||||
|
||||
function onClickPieChartItem(item: Record<string, unknown>): void {
|
||||
router.push(getTransactionItemLinkUrl(item['id'] as string));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user