support filtering geographic location and pictures in insights explorer

This commit is contained in:
MaysWind
2026-01-03 22:42:58 +08:00
parent 91a00cb5b3
commit 43154832b6
6 changed files with 134 additions and 2 deletions
+4
View File
@@ -21,7 +21,9 @@ export enum TransactionExplorerConditionFieldType {
DestinationAccount = 'destinationAccount',
SourceAmount = 'sourceAmount',
DestinationAmount = 'destinationAmount',
GeoLocation = 'geoLocation',
TransactionTag = 'transactionTag',
Pictures = 'pictures',
Description = 'description'
}
@@ -35,7 +37,9 @@ export class TransactionExplorerConditionField implements NameValue {
public static readonly DestinationAccount = new TransactionExplorerConditionField('Destination Account', TransactionExplorerConditionFieldType.DestinationAccount);
public static readonly SourceAmount = new TransactionExplorerConditionField('Amount', TransactionExplorerConditionFieldType.SourceAmount);
public static readonly DestinationAmount = new TransactionExplorerConditionField('Transfer In Amount', TransactionExplorerConditionFieldType.DestinationAmount);
public static readonly GeoLocation = new TransactionExplorerConditionField('Geographic Location', TransactionExplorerConditionFieldType.GeoLocation);
public static readonly TransactionTag = new TransactionExplorerConditionField('Tags', TransactionExplorerConditionFieldType.TransactionTag);
public static readonly Pictures = new TransactionExplorerConditionField('Pictures', TransactionExplorerConditionFieldType.Pictures);
public static readonly Description = new TransactionExplorerConditionField('Description', TransactionExplorerConditionFieldType.Description);
public readonly name: string;
+1 -1
View File
@@ -509,7 +509,7 @@ export default {
return axios.get<ApiResponse<TransactionInfoPageWrapperResponse2>>(`v1/transactions/list/by_month.json?year=${req.year}&month=${req.month}&type=${req.type}&category_ids=${req.categoryIds}&account_ids=${req.accountIds}&tag_filter=${tagFilter}&amount_filter=${amountFilter}&keyword=${keyword}&trim_account=true&trim_category=true&trim_tag=true`);
},
getAllTransactions: (req: TransactionAllListRequest): ApiResponsePromise<TransactionInfoResponse[]> => {
return axios.get<ApiResponse<TransactionInfoResponse[]>>(`v1/transactions/list/all.json?trim_account=true&trim_category=true&trim_tag=true&start_time=${req.startTime}&end_time=${req.endTime}`);
return axios.get<ApiResponse<TransactionInfoResponse[]>>(`v1/transactions/list/all.json?trim_account=true&with_pictures=${!!req.withPictures}&trim_category=true&trim_tag=true&start_time=${req.startTime}&end_time=${req.endTime}`);
},
getReconciliationStatements: (req: TransactionReconciliationStatementRequest): ApiResponsePromise<TransactionReconciliationStatementResponse> => {
return axios.get<ApiResponse<TransactionReconciliationStatementResponse>>(`v1/transactions/reconciliation_statements.json?account_id=${req.accountId}&start_time=${req.startTime}&end_time=${req.endTime}`);
+116
View File
@@ -51,9 +51,15 @@ export class TransactionExplorerQuery {
case TransactionExplorerConditionField.DestinationAmount:
condition = new TransactionExplorerDestinationAmountCondition(TransactionExplorerConditionOperatorType.Between, [0, 0]);
break;
case TransactionExplorerConditionField.GeoLocation:
condition = new TransactionExplorerGeoLocationCondition(TransactionExplorerConditionOperatorType.IsNotEmpty, []);
break;
case TransactionExplorerConditionField.TransactionTag:
condition = new TransactionExplorerTransactionTagCondition(TransactionExplorerConditionOperatorType.HasAny, []);
break;
case TransactionExplorerConditionField.Pictures:
condition = new TransactionExplorerPicturesCondition(TransactionExplorerConditionOperatorType.IsNotEmpty, []);
break;
case TransactionExplorerConditionField.Description:
condition = new TransactionExplorerDescriptionCondition(TransactionExplorerConditionOperatorType.Contains, '');
break;
@@ -302,9 +308,15 @@ export class TransactionExplorerConditionWithRelation {
case TransactionExplorerConditionField.DestinationAmount.value:
operatorTypes = TransactionExplorerDestinationAmountCondition.supportedOperators;
break;
case TransactionExplorerConditionField.GeoLocation.value:
operatorTypes = TransactionExplorerGeoLocationCondition.supportedOperators;
break;
case TransactionExplorerConditionField.TransactionTag.value:
operatorTypes = TransactionExplorerTransactionTagCondition.supportedOperators;
break;
case TransactionExplorerConditionField.Pictures.value:
operatorTypes = TransactionExplorerPicturesCondition.supportedOperators;
break;
case TransactionExplorerConditionField.Description.value:
operatorTypes = TransactionExplorerDescriptionCondition.supportedOperators;
break;
@@ -385,11 +397,21 @@ export class TransactionExplorerConditionWithRelation {
condition = new TransactionExplorerDestinationAmountCondition(conditionOperator as AmountConditionOperator, conditionValue as [number, number]);
}
break;
case TransactionExplorerConditionField.GeoLocation.value:
if (TransactionExplorerGeoLocationCondition.supportedOperators[conditionOperator] && Array.isArray(conditionValue)) {
condition = new TransactionExplorerGeoLocationCondition(conditionOperator as GeoLocationConditionOperator, conditionValue as string[]);
}
break;
case TransactionExplorerConditionField.TransactionTag.value:
if (TransactionExplorerTransactionTagCondition.supportedOperators[conditionOperator] && Array.isArray(conditionValue)) {
condition = new TransactionExplorerTransactionTagCondition(conditionOperator as TransactionTagConditionOperator, conditionValue as string[]);
}
break;
case TransactionExplorerConditionField.Pictures.value:
if (TransactionExplorerPicturesCondition.supportedOperators[conditionOperator] && Array.isArray(conditionValue)) {
condition = new TransactionExplorerPicturesCondition(conditionOperator as PicturesConditionOperator, conditionValue as string[]);
}
break;
case TransactionExplorerConditionField.Description.value:
if (TransactionExplorerDescriptionCondition.supportedOperators[conditionOperator] && typeof conditionValue === 'string') {
condition = new TransactionExplorerDescriptionCondition(conditionOperator as DescriptionConditionOperator, conditionValue);
@@ -690,6 +712,53 @@ export class TransactionExplorerDestinationAmountCondition extends AbstractTrans
}
}
type GeoLocationConditionOperator = TransactionExplorerConditionOperatorType.IsEmpty |
TransactionExplorerConditionOperatorType.IsNotEmpty;
export class TransactionExplorerGeoLocationCondition implements TransactionExplorerCondition<TransactionExplorerConditionFieldType.GeoLocation, string[]> {
public static readonly supportedOperators: PartialRecord<TransactionExplorerConditionOperatorType, true> = {
[TransactionExplorerConditionOperatorType.IsEmpty]: true,
[TransactionExplorerConditionOperatorType.IsNotEmpty]: true
};
public readonly field = TransactionExplorerConditionFieldType.GeoLocation;
public readonly operator: GeoLocationConditionOperator = TransactionExplorerConditionOperatorType.IsNotEmpty;
public value: string[];
constructor(operator: GeoLocationConditionOperator, value: string[]) {
this.operator = operator;
this.value = value;
}
public getValueForStore(): string[] {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty || this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return [];
}
return [];
}
public match(transaction: TransactionInsightDataItem): boolean {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty) {
return !transaction.geoLocation;
} else if (this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return !!transaction.geoLocation;
}
return false;
}
public toExpression(): string {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty) {
return `geo_location IS EMPTY`;
} else if (this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return `geo_location IS NOT EMPTY`;
}
return '';
}
}
type TransactionTagConditionOperator = TransactionExplorerConditionOperatorType.IsEmpty |
TransactionExplorerConditionOperatorType.IsNotEmpty |
TransactionExplorerConditionOperatorType.Equals |
@@ -825,6 +894,53 @@ export class TransactionExplorerTransactionTagCondition implements TransactionEx
}
}
type PicturesConditionOperator = TransactionExplorerConditionOperatorType.IsEmpty |
TransactionExplorerConditionOperatorType.IsNotEmpty;
export class TransactionExplorerPicturesCondition implements TransactionExplorerCondition<TransactionExplorerConditionFieldType.Pictures, string[]> {
public static readonly supportedOperators: PartialRecord<TransactionExplorerConditionOperatorType, true> = {
[TransactionExplorerConditionOperatorType.IsEmpty]: true,
[TransactionExplorerConditionOperatorType.IsNotEmpty]: true
};
public readonly field = TransactionExplorerConditionFieldType.Pictures;
public readonly operator: PicturesConditionOperator = TransactionExplorerConditionOperatorType.IsNotEmpty;
public value: string[];
constructor(operator: PicturesConditionOperator, value: string[]) {
this.operator = operator;
this.value = value;
}
public getValueForStore(): string[] {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty || this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return [];
}
return [];
}
public match(transaction: TransactionInsightDataItem): boolean {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty) {
return !transaction.pictures || transaction.pictures.length < 1;
} else if (this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return !!transaction.pictures && transaction.pictures.length > 0;
}
return false;
}
public toExpression(): string {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty) {
return `pictures IS EMPTY`;
} else if (this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return `pictures IS NOT EMPTY`;
}
return '';
}
}
type DescriptionConditionOperator = TransactionExplorerConditionOperatorType.IsEmpty |
TransactionExplorerConditionOperatorType.IsNotEmpty |
TransactionExplorerConditionOperatorType.Equals |
+1
View File
@@ -600,6 +600,7 @@ export interface TransactionListInMonthByPageRequest {
export interface TransactionAllListRequest {
readonly startTime: number;
readonly endTime: number;
readonly withPictures?: boolean;
}
export interface TransactionReconciliationStatementRequest {
+2 -1
View File
@@ -857,7 +857,8 @@ export const useExplorersStore = defineStore('explorers', () => {
return new Promise((resolve, reject) => {
services.getAllTransactions({
startTime: transactionExplorerFilter.value.startTime,
endTime: transactionExplorerFilter.value.endTime
endTime: transactionExplorerFilter.value.endTime,
withPictures: true
}).then(response => {
const data = response.data;
@@ -221,6 +221,11 @@
/>
</div>
<v-text-field disabled density="compact"
:placeholder="tt('None')"
v-else-if="conditionWithRelation.condition.field === TransactionExplorerConditionField.GeoLocation.value"
/>
<div class="d-flex w-100" v-else-if="conditionWithRelation.condition.field === TransactionExplorerConditionField.TransactionTag.value">
<v-text-field
disabled
@@ -283,6 +288,11 @@
</v-autocomplete>
</div>
<v-text-field disabled density="compact"
:placeholder="tt('None')"
v-else-if="conditionWithRelation.condition.field === TransactionExplorerConditionField.Pictures.value"
/>
<v-text-field disabled density="compact"
:placeholder="tt('None')"
v-else-if="conditionWithRelation.condition.field === TransactionExplorerConditionField.Description.value &&