fix some number value not display localized decimal symbol

This commit is contained in:
MaysWind
2025-05-04 21:30:04 +08:00
parent dc24186ccb
commit d036f66d4c
6 changed files with 100 additions and 15 deletions
+1 -2
View File
@@ -5,7 +5,6 @@ import { useI18n } from '@/locales/helpers.ts';
import { DEFAULT_CHART_COLORS } from '@/consts/color.ts'; import { DEFAULT_CHART_COLORS } from '@/consts/color.ts';
import { isNumber } from '@/lib/common.ts'; import { isNumber } from '@/lib/common.ts';
import { formatPercent } from '@/lib/numeral.ts';
export interface CommonPieChartDataItem { export interface CommonPieChartDataItem {
id: string; id: string;
@@ -36,7 +35,7 @@ export interface CommonPieChartProps {
} }
export function usePieChartBase(props: CommonPieChartProps) { export function usePieChartBase(props: CommonPieChartProps) {
const { formatAmountWithCurrency } = useI18n(); const { formatAmountWithCurrency, formatPercent } = useI18n();
const selectedIndex = ref<number>(0); const selectedIndex = ref<number>(0);
+81 -6
View File
@@ -1,7 +1,7 @@
import { type NumberFormatOptions, DecimalSeparator, DigitGroupingSymbol, DigitGroupingType} from '@/core/numeral.ts'; import { type NumberFormatOptions, DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts';
import { DEFAULT_DECIMAL_NUMBER_COUNT, MAX_SUPPORTED_DECIMAL_NUMBER_COUNT } from '@/consts/numeral.ts'; import { DEFAULT_DECIMAL_NUMBER_COUNT, MAX_SUPPORTED_DECIMAL_NUMBER_COUNT } from '@/consts/numeral.ts';
import { isString, isNumber, removeAll } from './common.ts'; import {isString, isNumber, replaceAll, removeAll } from './common.ts';
export function appendDigitGroupingSymbol(value: number | string, options: NumberFormatOptions): string { export function appendDigitGroupingSymbol(value: number | string, options: NumberFormatOptions): string {
let textualValue = ''; let textualValue = '';
@@ -76,6 +76,67 @@ export function appendDigitGroupingSymbol(value: number | string, options: Numbe
} }
} }
export function appendDecimalSeparator(value: number | string, options: NumberFormatOptions): string {
let textualValue = '';
if (isNumber(value)) {
textualValue = value.toString();
} else {
textualValue = value;
}
if (!textualValue) {
return textualValue;
}
if (!options) {
options = {};
}
if (!isString(options.decimalSeparator)) {
return textualValue;
}
if (textualValue.length < 1) {
return textualValue;
}
const negative = textualValue.charAt(0) === '-';
if (negative) {
textualValue = textualValue.substring(1);
}
const decimalSeparator = options.decimalSeparator || DecimalSeparator.Default.symbol;
let currentDecimalSeparator = '';
let integer = '';
let decimals = '';
for (let i = 0; i < textualValue.length; i++) {
const ch = textualValue.charAt(i);
if ('0' <= ch && ch <= '9') {
integer += ch;
} else {
currentDecimalSeparator = ch;
decimals = textualValue.substring(i + 1);
break;
}
}
if (negative) {
integer = `-${integer}`;
}
if (currentDecimalSeparator) {
return `${integer}${decimalSeparator}${decimals}`;
} else {
return integer;
}
}
export function parseAmount(str: string, options: NumberFormatOptions): number { export function parseAmount(str: string, options: NumberFormatOptions): number {
if (!isString(str)) { if (!isString(str)) {
return 0; return 0;
@@ -208,16 +269,30 @@ export function formatAmount(value: number | string, options: NumberFormatOption
return textualValue; return textualValue;
} }
export function formatPercent(value: number, precision: number, lowPrecisionValue: string): string { export function formatNumber(value: number, precision: number, options: NumberFormatOptions): string {
const ratio = Math.pow(10, precision);
const normalizedValue = Math.floor(value * ratio);
const textualValue = (normalizedValue / ratio).toString();
return appendDecimalSeparator(textualValue, options);
}
export function formatPercent(value: number, precision: number, lowPrecisionValue: string, options: NumberFormatOptions): string {
const ratio = Math.pow(10, precision); const ratio = Math.pow(10, precision);
const normalizedValue = Math.floor(value * ratio); const normalizedValue = Math.floor(value * ratio);
if (value > 0 && normalizedValue < 1 && lowPrecisionValue) { if (value > 0 && normalizedValue < 1 && lowPrecisionValue) {
return lowPrecisionValue + '%'; const systemDecimalSeparator = DecimalSeparator.Dot.symbol;
const decimalSeparator = options.decimalSeparator || DecimalSeparator.Default.symbol;
if (systemDecimalSeparator === decimalSeparator) {
return lowPrecisionValue + '%';
}
return replaceAll(lowPrecisionValue, systemDecimalSeparator, decimalSeparator) + '%';
} }
const result = normalizedValue / ratio; return formatNumber(value, precision, options) + '%';
return result + '%';
} }
export function getAmountWithDecimalNumberCount(amount: number, decimalNumberCount: number): number { export function getAmountWithDecimalNumberCount(amount: number, decimalNumberCount: number): number {
+14
View File
@@ -137,6 +137,8 @@ import {
appendDigitGroupingSymbol, appendDigitGroupingSymbol,
parseAmount, parseAmount,
formatAmount, formatAmount,
formatNumber,
formatPercent,
formatExchangeRateAmount, formatExchangeRateAmount,
getAdaptiveDisplayAmountRate getAdaptiveDisplayAmountRate
} from '@/lib/numeral.ts'; } from '@/lib/numeral.ts';
@@ -1472,6 +1474,16 @@ export function useI18n() {
return appendCurrencySymbol(textualValue, currencyDisplayType, finalCurrencyCode, currencyUnit, currencyName, isPlural); return appendCurrencySymbol(textualValue, currencyDisplayType, finalCurrencyCode, currencyUnit, currencyName, isPlural);
} }
function getFormattedNumber(value: number, precision: number): string {
const numberFormatOptions = getNumberFormatOptions();
return formatNumber(value, precision, numberFormatOptions);
}
function getFormattedPercentValue(value: number, precision: number, lowPrecisionValue: string): string {
const numberFormatOptions = getNumberFormatOptions();
return formatPercent(value, precision, lowPrecisionValue, numberFormatOptions);
}
function getFormattedExchangeRateAmount(value: number | string): string { function getFormattedExchangeRateAmount(value: number | string): string {
const numberFormatOptions = getNumberFormatOptions(); const numberFormatOptions = getNumberFormatOptions();
return formatExchangeRateAmount(value, numberFormatOptions); return formatExchangeRateAmount(value, numberFormatOptions);
@@ -1746,6 +1758,8 @@ export function useI18n() {
parseAmount: getParsedAmountNumber, parseAmount: getParsedAmountNumber,
formatAmount: getFormattedAmount, formatAmount: getFormattedAmount,
formatAmountWithCurrency: getFormattedAmountWithCurrency, formatAmountWithCurrency: getFormattedAmountWithCurrency,
formatNumber: getFormattedNumber,
formatPercent: getFormattedPercentValue,
formatExchangeRateAmount: getFormattedExchangeRateAmount, formatExchangeRateAmount: getFormattedExchangeRateAmount,
getAdaptiveAmountRate, getAdaptiveAmountRate,
getAmountPrependAndAppendText, getAmountPrependAndAppendText,
@@ -352,9 +352,6 @@ import {
isNumber, isNumber,
arrayItemToObjectField arrayItemToObjectField
} from '@/lib/common.ts' } from '@/lib/common.ts'
import {
formatPercent
} from '@/lib/numeral.ts';
import { import {
getYearAndMonthFromUnixTime, getYearAndMonthFromUnixTime,
getYearMonthFirstUnixTime, getYearMonthFirstUnixTime,
@@ -399,7 +396,7 @@ const props = defineProps<TransactionStatisticsProps>();
const router = useRouter(); const router = useRouter();
const display = useDisplay(); const display = useDisplay();
const theme = useTheme(); const theme = useTheme();
const { tt, getAllCategoricalChartTypes, getAllTrendChartTypes } = useI18n(); const { tt, getAllCategoricalChartTypes, getAllTrendChartTypes, formatPercent } = useI18n();
const { const {
loading, loading,
@@ -786,7 +786,7 @@
<v-btn color="teal" :disabled="submitting || !!editingTransaction || selectedImportTransactionCount < 1 || selectedInvalidTransactionCount > 0" <v-btn color="teal" :disabled="submitting || !!editingTransaction || selectedImportTransactionCount < 1 || selectedInvalidTransactionCount > 0"
:append-icon="!submitting ? mdiArrowRight : undefined" @click="submit" :append-icon="!submitting ? mdiArrowRight : undefined" @click="submit"
v-if="currentStep === 'checkData'"> v-if="currentStep === 'checkData'">
{{ (submitting && importProcess > 0 ? tt('format.misc.importingTransactions', { process: importProcess.toFixed(2) }) : tt('Import')) }} {{ (submitting && importProcess > 0 ? tt('format.misc.importingTransactions', { process: formatNumber(importProcess, 2) }) : tt('Import')) }}
<v-progress-circular indeterminate size="22" class="ml-2" v-if="submitting"></v-progress-circular> <v-progress-circular indeterminate size="22" class="ml-2" v-if="submitting"></v-progress-circular>
</v-btn> </v-btn>
<v-btn color="secondary" variant="tonal" <v-btn color="secondary" variant="tonal"
@@ -948,6 +948,7 @@ const {
getAllSupportedImportFileTypes, getAllSupportedImportFileTypes,
formatUnixTimeToLongDateTime, formatUnixTimeToLongDateTime,
formatAmountWithCurrency, formatAmountWithCurrency,
formatNumber,
getCategorizedAccountsWithDisplayBalance getCategorizedAccountsWithDisplayBalance
} = useI18n(); } = useI18n();
@@ -344,7 +344,6 @@ import {
} from '@/core/statistics.ts'; } from '@/core/statistics.ts';
import { isString, isNumber } from '@/lib/common.ts'; import { isString, isNumber } from '@/lib/common.ts';
import { formatPercent } from '@/lib/numeral.ts';
import { import {
getYearAndMonthFromUnixTime, getYearAndMonthFromUnixTime,
getYearMonthFirstUnixTime, getYearMonthFirstUnixTime,
@@ -359,7 +358,7 @@ const props = defineProps<{
f7router: Router.Router; f7router: Router.Router;
}>(); }>();
const { tt, getAllCategoricalChartTypes } = useI18n(); const { tt, getAllCategoricalChartTypes, formatPercent } = useI18n();
const { showToast, routeBackOnError } = useI18nUIComponents(); const { showToast, routeBackOnError } = useI18nUIComponents();
const { const {