support automatically applying known column mapping and transaction type mapping rules when importing custom files with column mapping handle method

This commit is contained in:
MaysWind
2026-03-01 16:32:22 +08:00
parent d7a0d253c4
commit c6eb3cfb74
2 changed files with 279 additions and 1 deletions
@@ -224,7 +224,7 @@
import SnackBar from '@/components/desktop/SnackBar.vue';
import PaginationButtons from '@/components/desktop/PaginationButtons.vue';
import { ref, computed, useTemplateRef } from 'vue';
import { ref, computed, useTemplateRef, watch } from 'vue';
import { useI18n } from '@/locales/helpers.ts';
@@ -235,6 +235,7 @@ import { KnownDateTimezoneFormat } from '@/core/timezone.ts';
import { TransactionType } from '@/core/transaction.ts';
import { ImportTransactionColumnType, ImportTransactionDataMapping } from '@/core/import_transaction.ts';
import { KnownFileType } from '@/core/file.ts';
import { KNOWN_COLUMN_NAME_MAPPING, KNOWN_TRANSACTION_TYPE_NAME_MAPPING } from '@/consts/import_transaction.ts';
import {
isNumber,
@@ -477,6 +478,10 @@ function getTablePageOptions(linesCount?: number): NameNumeralValue[] {
return pageOptions;
}
function getNormalizedKey(key: string): string {
return key.toLowerCase().replaceAll(' ', '').replaceAll('_', '').replaceAll('-', '');
}
function getParseDataMappedColumnDisplayName(columnIndex: number): string {
for (const [columnType, index] of entries(parsedFileDataColumnMapping.value.dataColumnMapping)) {
if (index === columnIndex) {
@@ -487,6 +492,72 @@ function getParseDataMappedColumnDisplayName(columnIndex: number): string {
return tt('Unspecified');
}
function autoSetColumnMapping(): void {
if (!props.parsedFileData) {
return;
}
const firstLine: string[] = props.parsedFileData.length > 0 ? (props.parsedFileData[0] as string[]) : [];
const displayColumnNamesMap: Record<string, ImportTransactionColumnType> = {};
for (const column of ImportTransactionColumnType.values()) {
displayColumnNamesMap[getNormalizedKey(tt(column.name))] = column;
}
for (const [columnName, index] of itemAndIndex(firstLine)) {
const normalizedColumnName = getNormalizedKey(columnName);
if (displayColumnNamesMap[normalizedColumnName]) {
const columnType = displayColumnNamesMap[normalizedColumnName];
if (!isNumber(parsedFileDataColumnMapping.value.dataColumnMapping[columnType.type])) {
parsedFileDataColumnMapping.value.dataColumnMapping[columnType.type] = index;
}
continue;
}
if (KNOWN_COLUMN_NAME_MAPPING[normalizedColumnName]) {
const columnType = KNOWN_COLUMN_NAME_MAPPING[normalizedColumnName];
if (!isNumber(parsedFileDataColumnMapping.value.dataColumnMapping[columnType.type])) {
parsedFileDataColumnMapping.value.dataColumnMapping[columnType.type] = index;
}
continue;
}
}
}
function autoSetTransactionTypeMapping(): void {
if (!props.parsedFileData) {
return;
}
const displayTransactinTypeNamesMap: Record<string, TransactionType> = {
[getNormalizedKey(tt('Modify Balance'))]: TransactionType.ModifyBalance,
[getNormalizedKey(tt('Income'))]: TransactionType.Income,
[getNormalizedKey(tt('Expense'))]: TransactionType.Expense,
[getNormalizedKey(tt('Transfer'))]: TransactionType.Transfer
};
for (const transactionTypeName of parsedFileAllTransactionTypes.value) {
const normalizedTransactionTypeName = getNormalizedKey(transactionTypeName);
if (displayTransactinTypeNamesMap[normalizedTransactionTypeName]) {
const transactionType = displayTransactinTypeNamesMap[normalizedTransactionTypeName];
parsedFileDataColumnMapping.value.transactionTypeMapping[transactionTypeName] = transactionType;
continue;
}
if (KNOWN_TRANSACTION_TYPE_NAME_MAPPING[normalizedTransactionTypeName]) {
const transactionType = KNOWN_TRANSACTION_TYPE_NAME_MAPPING[normalizedTransactionTypeName];
parsedFileDataColumnMapping.value.transactionTypeMapping[transactionTypeName] = transactionType;
continue;
}
}
}
function generateResult(): ImportTransactionDefineColumnResult | undefined {
const columnMapping: Record<number, number> = parsedFileDataColumnMapping.value.dataColumnMapping;
const transactionTypeMapping: Record<string, TransactionType> = parsedFileValidMappedTransactionTypes.value;
@@ -588,6 +659,13 @@ function saveColumnMappingFile(): void {
startDownloadFile(fileName, KnownFileType.JSON.createBlob(parsedFileDataColumnMapping.value.toJson()));
}
watch(() => props.parsedFileData, (newValue, oldValue) => {
if (newValue && !oldValue && getObjectOwnFieldCount(parsedFileDataColumnMapping.value.dataColumnMapping) < 1) {
autoSetColumnMapping();
autoSetTransactionTypeMapping();
}
}, { immediate: true });
defineExpose({
menus,
generateResult,