diff --git a/src/consts/api.ts b/src/consts/api.ts index e84b2c9c..95b8be2e 100644 --- a/src/consts/api.ts +++ b/src/consts/api.ts @@ -17,6 +17,7 @@ export const AMAP_JAVASCRIPT_URL: string = 'https://webapi.amap.com/maps?v=2.0'; export enum KnownErrorCode { ApiNotFound = 100001, ValidatorError = 200000, + NothingWillBeUpdated = 200004, UserEmailNotVerified = 201020, TwoFactorAuthorizationPasscodeEmpty = 203005, TransactionCannotCreateInThisTime = 205017, diff --git a/src/views/desktop/insights/ExplorerPage.vue b/src/views/desktop/insights/ExplorerPage.vue index a13219d7..92320399 100644 --- a/src/views/desktop/insights/ExplorerPage.vue +++ b/src/views/desktop/insights/ExplorerPage.vue @@ -74,7 +74,9 @@ {{ tt('Refresh') }} - {{ tt('Save Explorer') }} @@ -171,7 +173,7 @@ import ExplorerRenameDialog from '@/views/desktop/insights/dialogs/ExplorerRenam import EditDialog from '@/views/desktop/transactions/list/dialogs/EditDialog.vue'; import ExportDialog from '@/views/desktop/statistics/transaction/dialogs/ExportDialog.vue'; -import { ref, computed, useTemplateRef, watch } from 'vue'; +import { ref, computed, useTemplateRef, watch, nextTick } from 'vue'; import { useRouter, onBeforeRouteUpdate } from 'vue-router'; import { useDisplay } from 'vuetify'; @@ -187,6 +189,7 @@ import { type TransactionExplorerPartialFilter, type TransactionExplorerFilter, import type { TypeAndDisplayName } from '@/core/base.ts'; import { type WeekDayValue, type LocalizedDateRange, DateRangeScene, DateRange } from '@/core/datetime.ts'; import { TimezoneTypeForStatistics } from '@/core/timezone.ts'; +import { KnownErrorCode } from '@/consts/api.ts'; import { type TransactionInsightDataItem, Transaction } from '@/models/transaction.ts'; import { InsightsExplorerBasicInfo, InsightsExplorer } from '@/models/explorer.ts'; @@ -270,6 +273,7 @@ const loading = ref(true); const initing = ref(true); const updating = ref(false); const clientSessionId = ref(''); +const isCurrentExplorerModified = ref(false); const alwaysShowNav = ref(display.mdAndUp.value); const showNav = ref(display.mdAndUp.value); const activeTab = ref('query'); @@ -375,6 +379,7 @@ function init(initProps: InsightsExplorerProps): void { } } else { explorersStore.updateCurrentInsightsExplorer(InsightsExplorer.createNewExplorer(generateRandomUUID())); + isCurrentExplorerModified.value = true; } if (!needReload && !explorersStore.transactionExplorerStateInvalid && !explorersStore.insightsExplorerListStateInvalid) { @@ -429,6 +434,7 @@ function createNewExplorer(): void { } explorersStore.updateCurrentInsightsExplorer(InsightsExplorer.createNewExplorer(generateRandomUUID())); + isCurrentExplorerModified.value = true; router.push(getFilterLinkUrl()); } @@ -443,6 +449,11 @@ function loadExplorer(explorerId: string): void { explorerId: explorerId }).then(explorer => { explorersStore.updateCurrentInsightsExplorer(explorer); + + nextTick(() => { + isCurrentExplorerModified.value = false; + }); + loading.value = false; router.push(getFilterLinkUrl()); }).catch(error => { @@ -479,6 +490,10 @@ function doSaveExplorer(saveAs?: boolean): Promise { clientSessionId.value = generateRandomUUID(); explorersStore.updateCurrentInsightsExplorer(newExplorer); + nextTick(() => { + isCurrentExplorerModified.value = false; + }); + if (oldExplorerId !== newExplorer.id) { router.push(getFilterLinkUrl()); } @@ -487,6 +502,12 @@ function doSaveExplorer(saveAs?: boolean): Promise { if (!error.processed) { snackbar.value?.showError(error); + + if (error.error && error.error.errorCode === KnownErrorCode.NothingWillBeUpdated) { + nextTick(() => { + isCurrentExplorerModified.value = false; + }); + } } }); } @@ -506,6 +527,10 @@ function hideExplorer(hidden: boolean): void { }).then(() => { updating.value = false; currentExplorer.value.hidden = hidden; + + nextTick(() => { + isCurrentExplorerModified.value = false; + }); }).catch(error => { updating.value = false; @@ -670,5 +695,15 @@ watch(activeTab, () => { router.push(getFilterLinkUrl()); }); +watch(currentExplorer, () => { + if (initing.value || loading.value) { + return; + } + + isCurrentExplorerModified.value = true; +}, { + deep: true +}); + init(props);