mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-19 17:24:26 +08:00
support transaction tag filter type
This commit is contained in:
@@ -36,6 +36,27 @@ const allTransactionEditScopeTypes = {
|
||||
}
|
||||
};
|
||||
|
||||
const allTransactionTagFilterTypes = {
|
||||
HasAny: {
|
||||
type: 0,
|
||||
name: 'With Any Selected Tags'
|
||||
},
|
||||
HasAll: {
|
||||
type: 1,
|
||||
name: 'With All Selected Tags'
|
||||
},
|
||||
NotHasAny: {
|
||||
type: 2,
|
||||
name: 'Without Any Selected Tags'
|
||||
},
|
||||
NotHasAll: {
|
||||
type: 3,
|
||||
name: 'Without All Selected Tags'
|
||||
}
|
||||
};
|
||||
|
||||
const defaultTransactionTagFilterType = allTransactionTagFilterTypes.HasAny;
|
||||
|
||||
const minAmountNumber = -99999999999; // -999999999.99
|
||||
const maxAmountNumber = 99999999999; // 999999999.99
|
||||
const maxPictureCount = 10;
|
||||
@@ -43,6 +64,8 @@ const maxPictureCount = 10;
|
||||
export default {
|
||||
allTransactionTypes: allTransactionTypes,
|
||||
allTransactionEditScopeTypes: allTransactionEditScopeTypes,
|
||||
allTransactionTagFilterTypes: allTransactionTagFilterTypes,
|
||||
defaultTransactionTagFilterType: defaultTransactionTagFilterType,
|
||||
minAmountNumber: minAmountNumber,
|
||||
maxAmountNumber: maxAmountNumber,
|
||||
maxPictureCount: maxPictureCount,
|
||||
|
||||
@@ -1212,6 +1212,25 @@ function getAllTransactionEditScopeTypes(translateFn) {
|
||||
return allEditScopeTypes;
|
||||
}
|
||||
|
||||
function getAllTransactionTagFilterTypes(translateFn) {
|
||||
const allTagFilterTypes = [];
|
||||
|
||||
for (const typeName in transactionConstants.allTransactionTagFilterTypes) {
|
||||
if (!Object.prototype.hasOwnProperty.call(transactionConstants.allTransactionTagFilterTypes, typeName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const tagFilterType = transactionConstants.allTransactionTagFilterTypes[typeName];
|
||||
|
||||
allTagFilterTypes.push({
|
||||
type: tagFilterType.type,
|
||||
displayName: translateFn(tagFilterType.name)
|
||||
});
|
||||
}
|
||||
|
||||
return allTagFilterTypes;
|
||||
}
|
||||
|
||||
function getAllTransactionScheduledFrequencyTypes(translateFn) {
|
||||
const allScheduledFrequencyTypes = [];
|
||||
|
||||
@@ -1756,6 +1775,7 @@ export function i18nFunctions(i18nGlobal) {
|
||||
getAllStatisticsSortingTypes: () => getAllStatisticsSortingTypes(i18nGlobal.t),
|
||||
getAllStatisticsDateAggregationTypes: () => getAllStatisticsDateAggregationTypes(i18nGlobal.t),
|
||||
getAllTransactionEditScopeTypes: () => getAllTransactionEditScopeTypes(i18nGlobal.t),
|
||||
getAllTransactionTagFilterTypes: () => getAllTransactionTagFilterTypes(i18nGlobal.t),
|
||||
getAllTransactionScheduledFrequencyTypes: () => getAllTransactionScheduledFrequencyTypes(i18nGlobal.t),
|
||||
getAllTransactionDefaultCategories: (categoryType, locale) => getAllTransactionDefaultCategories(categoryType, locale, i18nGlobal.t),
|
||||
getAllDisplayExchangeRates: (settingsStore, exchangeRatesData) => getAllDisplayExchangeRates(settingsStore, exchangeRatesData, i18nGlobal.t),
|
||||
|
||||
+4
-4
@@ -299,15 +299,15 @@ export default {
|
||||
id
|
||||
});
|
||||
},
|
||||
getTransactions: ({ maxTime, minTime, count, page, withCount, type, categoryIds, accountIds, tagIds, amountFilter, keyword }) => {
|
||||
getTransactions: ({ maxTime, minTime, count, page, withCount, type, categoryIds, accountIds, tagIds, tagFilterType, amountFilter, keyword }) => {
|
||||
amountFilter = encodeURIComponent(amountFilter);
|
||||
keyword = encodeURIComponent(keyword);
|
||||
return axios.get(`v1/transactions/list.json?max_time=${maxTime}&min_time=${minTime}&type=${type}&category_ids=${categoryIds}&account_ids=${accountIds}&tag_ids=${tagIds}&amount_filter=${amountFilter}&keyword=${keyword}&count=${count}&page=${page}&with_count=${withCount}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||
return axios.get(`v1/transactions/list.json?max_time=${maxTime}&min_time=${minTime}&type=${type}&category_ids=${categoryIds}&account_ids=${accountIds}&tag_ids=${tagIds}&tag_filter_type=${tagFilterType}&amount_filter=${amountFilter}&keyword=${keyword}&count=${count}&page=${page}&with_count=${withCount}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||
},
|
||||
getAllTransactionsByMonth: ({ year, month, type, categoryIds, accountIds, tagIds, amountFilter, keyword }) => {
|
||||
getAllTransactionsByMonth: ({ year, month, type, categoryIds, accountIds, tagIds, tagFilterType, amountFilter, keyword }) => {
|
||||
amountFilter = encodeURIComponent(amountFilter);
|
||||
keyword = encodeURIComponent(keyword);
|
||||
return axios.get(`v1/transactions/list/by_month.json?year=${year}&month=${month}&type=${type}&category_ids=${categoryIds}&account_ids=${accountIds}&tag_ids=${tagIds}&amount_filter=${amountFilter}&keyword=${keyword}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||
return axios.get(`v1/transactions/list/by_month.json?year=${year}&month=${month}&type=${type}&category_ids=${categoryIds}&account_ids=${accountIds}&tag_ids=${tagIds}&tag_filter_type=${tagFilterType}&amount_filter=${amountFilter}&keyword=${keyword}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||
},
|
||||
getTransactionStatistics: ({ startTime, endTime, useTransactionTimezone }) => {
|
||||
const queryParams = [];
|
||||
|
||||
@@ -1177,6 +1177,7 @@
|
||||
"balanceTime": "Balance Time",
|
||||
"startTime": "Start Time",
|
||||
"endTime": "End Time",
|
||||
"tagFilterType": "Tag Filter Type",
|
||||
"amountFilter": "Amount Filter",
|
||||
"sourceAccountId": "Source Account ID",
|
||||
"destinationAccountId": "Destination Account ID",
|
||||
@@ -1515,6 +1516,10 @@
|
||||
"Source Account": "Source Account",
|
||||
"Destination Account": "Destination Account",
|
||||
"Without Tags": "Without Tags",
|
||||
"With Any Selected Tags": "With Any Selected Tags",
|
||||
"With All Selected Tags": "With All Selected Tags",
|
||||
"Without Any Selected Tags": "Without Any Selected Tags",
|
||||
"Without All Selected Tags": "Without All Selected Tags",
|
||||
"Multiple Tags": "Multiple Tags",
|
||||
"Transaction Time": "Transaction Time",
|
||||
"Scheduled Transaction Frequency": "Scheduled Transaction Frequency",
|
||||
|
||||
@@ -1177,6 +1177,7 @@
|
||||
"balanceTime": "Thời gian số dư",
|
||||
"startTime": "Thời gian bắt đầu",
|
||||
"endTime": "Thời gian kết thúc",
|
||||
"tagFilterType": "Tag Filter Type",
|
||||
"amountFilter": "Bộ lọc số tiền",
|
||||
"sourceAccountId": "ID tài khoản nguồn",
|
||||
"destinationAccountId": "ID tài khoản đích",
|
||||
@@ -1515,6 +1516,10 @@
|
||||
"Source Account": "Tài khoản nguồn",
|
||||
"Destination Account": "Tài khoản đích",
|
||||
"Without Tags": "Không có thẻ",
|
||||
"With Any Selected Tags": "With Any Selected Tags",
|
||||
"With All Selected Tags": "With All Selected Tags",
|
||||
"Without Any Selected Tags": "Without Any Selected Tags",
|
||||
"Without All Selected Tags": "Without All Selected Tags",
|
||||
"Multiple Tags": "Nhiều thẻ",
|
||||
"Transaction Time": "Thời gian giao dịch",
|
||||
"Scheduled Transaction Frequency": "Tần suất giao dịch theo lịch trình",
|
||||
|
||||
@@ -1177,6 +1177,7 @@
|
||||
"balanceTime": "余额时间",
|
||||
"startTime": "开始时间",
|
||||
"endTime": "结束时间",
|
||||
"tagFilterType": "标签过滤类型",
|
||||
"amountFilter": "金额过滤",
|
||||
"sourceAccountId": "来源账户ID",
|
||||
"destinationAccountId": "目标账户ID",
|
||||
@@ -1515,6 +1516,10 @@
|
||||
"Source Account": "来源账户",
|
||||
"Destination Account": "目标账户",
|
||||
"Without Tags": "没有标签",
|
||||
"With Any Selected Tags": "包含任意选中的标签",
|
||||
"With All Selected Tags": "包含全部选中的标签",
|
||||
"Without Any Selected Tags": "不包含任意选中的标签",
|
||||
"Without All Selected Tags": "不包含全部选中的标签",
|
||||
"Multiple Tags": "多个标签",
|
||||
"Transaction Time": "交易时间",
|
||||
"Scheduled Transaction Frequency": "定时交易周期",
|
||||
|
||||
@@ -104,6 +104,7 @@ const router = createRouter({
|
||||
initCategoryIds: route.query.categoryIds,
|
||||
initAccountIds: route.query.accountIds,
|
||||
initTagIds: route.query.tagIds,
|
||||
initTagFilterType: route.query.tagFilterType,
|
||||
initAmountFilter: route.query.amountFilter,
|
||||
initKeyword: route.query.keyword
|
||||
})
|
||||
|
||||
@@ -374,6 +374,7 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
categoryIds: '',
|
||||
accountIds: '',
|
||||
tagIds: '',
|
||||
tagFilterType: transactionConstants.defaultTransactionTagFilterType.type,
|
||||
amountFilter: '',
|
||||
keyword: ''
|
||||
},
|
||||
@@ -671,6 +672,7 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
this.transactionsFilter.categoryIds = '';
|
||||
this.transactionsFilter.accountIds = '';
|
||||
this.transactionsFilter.tagIds = '';
|
||||
this.transactionsFilter.tagFilterType = transactionConstants.defaultTransactionTagFilterType.type;
|
||||
this.transactionsFilter.amountFilter = '';
|
||||
this.transactionsFilter.keyword = '';
|
||||
this.transactions = [];
|
||||
@@ -725,6 +727,12 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
this.transactionsFilter.tagIds = '';
|
||||
}
|
||||
|
||||
if (filter && isNumber(filter.tagFilterType)) {
|
||||
this.transactionsFilter.tagFilterType = filter.tagFilterType;
|
||||
} else {
|
||||
this.transactionsFilter.tagFilterType = transactionConstants.defaultTransactionTagFilterType.type;
|
||||
}
|
||||
|
||||
if (filter && isString(filter.amountFilter)) {
|
||||
this.transactionsFilter.amountFilter = filter.amountFilter;
|
||||
} else {
|
||||
@@ -775,6 +783,11 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (filter && isNumber(filter.tagFilterType) && this.transactionsFilter.tagFilterType !== filter.tagFilterType) {
|
||||
this.transactionsFilter.tagFilterType = filter.tagFilterType;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (filter && isString(filter.amountFilter) && this.transactionsFilter.amountFilter !== filter.amountFilter) {
|
||||
this.transactionsFilter.amountFilter = filter.amountFilter;
|
||||
changed = true;
|
||||
@@ -806,6 +819,10 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
querys.push('tagIds=' + this.transactionsFilter.tagIds);
|
||||
}
|
||||
|
||||
if (this.transactionsFilter.tagFilterType) {
|
||||
querys.push('tagFilterType=' + this.transactionsFilter.tagFilterType);
|
||||
}
|
||||
|
||||
querys.push('dateType=' + this.transactionsFilter.dateType);
|
||||
|
||||
if (this.transactionsFilter.dateType === datetimeConstants.allDateRanges.Custom.type) {
|
||||
@@ -846,6 +863,7 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
categoryIds: self.transactionsFilter.categoryIds,
|
||||
accountIds: self.transactionsFilter.accountIds,
|
||||
tagIds: self.transactionsFilter.tagIds,
|
||||
tagFilterType: self.transactionsFilter.tagFilterType,
|
||||
amountFilter: self.transactionsFilter.amountFilter,
|
||||
keyword: self.transactionsFilter.keyword
|
||||
}).then(response => {
|
||||
@@ -922,6 +940,7 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
categoryIds: self.transactionsFilter.categoryIds,
|
||||
accountIds: self.transactionsFilter.accountIds,
|
||||
tagIds: self.transactionsFilter.tagIds,
|
||||
tagFilterType: self.transactionsFilter.tagFilterType,
|
||||
amountFilter: self.transactionsFilter.amountFilter,
|
||||
keyword: self.transactionsFilter.keyword
|
||||
}).then(response => {
|
||||
|
||||
@@ -376,6 +376,25 @@
|
||||
</div>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider v-if="query.tagIds && query.tagIds !== 'none'" />
|
||||
|
||||
<template :key="filterType.type"
|
||||
v-for="filterType in allTransactionTagFilterTypes"
|
||||
v-if="query.tagIds && query.tagIds !== 'none'">
|
||||
<v-list-item class="text-sm" density="compact"
|
||||
:value="filterType.type"
|
||||
:append-icon="(query.tagFilterType === filterType.type ? icons.check : null)">
|
||||
<v-list-item-title class="cursor-pointer"
|
||||
@click="changeTagFilterType(filterType.type)">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon size="24" :icon="filterType.icon"/>
|
||||
<span class="text-sm ml-3">{{ filterType.displayName }}</span>
|
||||
</div>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
||||
<template :key="transactionTag.id"
|
||||
v-for="transactionTag in allTransactionTags">
|
||||
<v-divider v-if="!transactionTag.hidden || query.tagIds === transactionTag.id" />
|
||||
@@ -588,6 +607,10 @@ import {
|
||||
mdiPencilBoxOutline,
|
||||
mdiArrowLeft,
|
||||
mdiArrowRight,
|
||||
mdiPlusBoxMultipleOutline,
|
||||
mdiCheckboxMultipleOutline,
|
||||
mdiMinusBoxMultipleOutline,
|
||||
mdiCloseBoxMultipleOutline,
|
||||
mdiPound,
|
||||
mdiTextBoxOutline,
|
||||
mdiDotsVertical
|
||||
@@ -609,6 +632,7 @@ export default {
|
||||
'initCategoryIds',
|
||||
'initAccountIds',
|
||||
'initTagIds',
|
||||
'initTagFilterType',
|
||||
'initAmountFilter',
|
||||
'initKeyword'
|
||||
],
|
||||
@@ -649,6 +673,10 @@ export default {
|
||||
modifyBalance: mdiPencilBoxOutline,
|
||||
arrowLeft: mdiArrowLeft,
|
||||
arrowRight: mdiArrowRight,
|
||||
withAnyTags: mdiPlusBoxMultipleOutline,
|
||||
withAllTags: mdiCheckboxMultipleOutline,
|
||||
withoutAnyTags: mdiMinusBoxMultipleOutline,
|
||||
withoutAllTags: mdiCloseBoxMultipleOutline,
|
||||
tag: mdiPound,
|
||||
templates: mdiTextBoxOutline,
|
||||
more: mdiDotsVertical
|
||||
@@ -911,6 +939,26 @@ export default {
|
||||
allTransactionTypes() {
|
||||
return transactionConstants.allTransactionTypes;
|
||||
},
|
||||
allTransactionTagFilterTypes() {
|
||||
const allTagFilterTypes = this.$locale.getAllTransactionTagFilterTypes();
|
||||
const allTagFilterTypesWithIcon = [];
|
||||
const tagFilterIconMap = {
|
||||
[transactionConstants.allTransactionTagFilterTypes.HasAny.type]: this.icons.withAnyTags,
|
||||
[transactionConstants.allTransactionTagFilterTypes.HasAll.type]: this.icons.withAllTags,
|
||||
[transactionConstants.allTransactionTagFilterTypes.NotHasAny.type]: this.icons.withoutAnyTags,
|
||||
[transactionConstants.allTransactionTagFilterTypes.NotHasAll.type]: this.icons.withoutAllTags
|
||||
};
|
||||
|
||||
for (let i = 0; i < allTagFilterTypes.length; i++) {
|
||||
allTagFilterTypesWithIcon.push({
|
||||
type: allTagFilterTypes[i].type,
|
||||
displayName: allTagFilterTypes[i].displayName,
|
||||
icon: tagFilterIconMap[allTagFilterTypes[i].type]
|
||||
});
|
||||
}
|
||||
|
||||
return allTagFilterTypesWithIcon;
|
||||
},
|
||||
allAccounts() {
|
||||
return this.accountsStore.allAccountsMap;
|
||||
},
|
||||
@@ -985,6 +1033,7 @@ export default {
|
||||
categoryIds: this.initCategoryIds,
|
||||
accountIds: this.initAccountIds,
|
||||
tagIds: this.initTagIds,
|
||||
tagFilterType: this.initTagFilterType,
|
||||
amountFilter: this.initAmountFilter,
|
||||
keyword: this.initKeyword
|
||||
});
|
||||
@@ -1015,6 +1064,7 @@ export default {
|
||||
categoryIds: to.query.categoryIds,
|
||||
accountIds: to.query.accountIds,
|
||||
tagIds: to.query.tagIds,
|
||||
tagFilterType: to.query.tagFilterType,
|
||||
amountFilter: to.query.amountFilter,
|
||||
keyword: to.query.keyword
|
||||
});
|
||||
@@ -1042,6 +1092,7 @@ export default {
|
||||
categoryIds: query.categoryIds,
|
||||
accountIds: query.accountIds,
|
||||
tagIds: query.tagIds,
|
||||
tagFilterType: parseInt(query.tagFilterType) >= 0 ? parseInt(query.tagFilterType) : undefined,
|
||||
amountFilter: query.amountFilter || '',
|
||||
keyword: query.keyword || ''
|
||||
});
|
||||
@@ -1256,6 +1307,22 @@ export default {
|
||||
this.$router.push(this.getFilterLinkUrl());
|
||||
}
|
||||
},
|
||||
changeTagFilterType(filterType) {
|
||||
if (this.query.tagFilterType === filterType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const changed = this.transactionsStore.updateTransactionListFilter({
|
||||
tagFilterType: filterType
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
this.loading = true;
|
||||
this.currentPageTransactions = [];
|
||||
this.transactionsStore.clearTransactions();
|
||||
this.$router.push(this.getFilterLinkUrl());
|
||||
}
|
||||
},
|
||||
changeAmountFilter(filterType) {
|
||||
this.currentAmountFilterType = '';
|
||||
this.amountMenuState = false;
|
||||
|
||||
@@ -470,6 +470,21 @@
|
||||
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="query.tagIds && queryAllFilterTagIdsCount > 1"></f7-icon>
|
||||
</template>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item :title="filterType.displayName"
|
||||
:key="filterType.type"
|
||||
v-for="filterType in allTransactionTagFilterTypes"
|
||||
v-if="query.tagIds && query.tagIds !== 'none'"
|
||||
@click="changeTagFilterType(filterType.type)"
|
||||
>
|
||||
<template #after>
|
||||
<f7-icon class="list-item-checked-icon"
|
||||
f7="checkmark_alt"
|
||||
v-if="query.tagFilterType === filterType.type">
|
||||
</f7-icon>
|
||||
</template>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item :title="transactionTag.name"
|
||||
:class="{ 'list-item-selected': query.tagIds === transactionTag.id, 'item-in-multiple-selection': queryAllFilterTagIdsCount > 1 && queryAllFilterTagIds[transactionTag.id] }"
|
||||
:key="transactionTag.id"
|
||||
@@ -662,6 +677,9 @@ export default {
|
||||
allTransactionTypes() {
|
||||
return transactionConstants.allTransactionTypes;
|
||||
},
|
||||
allTransactionTagFilterTypes() {
|
||||
return this.$locale.getAllTransactionTagFilterTypes();
|
||||
},
|
||||
allAccounts() {
|
||||
return this.accountsStore.allAccountsMap;
|
||||
},
|
||||
@@ -979,6 +997,21 @@ export default {
|
||||
this.reload(null);
|
||||
}
|
||||
},
|
||||
changeTagFilterType(filterType) {
|
||||
if (this.query.tagFilterType === filterType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const changed = this.transactionsStore.updateTransactionListFilter({
|
||||
tagFilterType: filterType
|
||||
});
|
||||
|
||||
this.showMorePopover = false;
|
||||
|
||||
if (changed) {
|
||||
this.reload(null);
|
||||
}
|
||||
},
|
||||
changeAmountFilter(filterType) {
|
||||
if (this.query.amountFilter === filterType) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user