fix: accuracy loss in bigint field read pretty (#4360)

* fix: accuracy loss in bigint field read pretty

* fix: accuracy loss in bigint field read pretty

* fix: accuracy loss in bigint field read pretty

* fix: accuracy loss in bigint field read pretty

* fix: accuracy loss in bigint field read pretty

* test: intege test

* test: color test
This commit is contained in:
Katherine 2024-05-17 08:32:21 +08:00 committed by GitHub
parent 46452ef275
commit 779029e348
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 57 additions and 8 deletions

View File

@ -12,6 +12,7 @@ import { toFixedByStep } from '@nocobase/utils/client';
import { format } from 'd3-format';
import * as math from 'mathjs';
import React, { useMemo } from 'react';
import BigNumber from 'bignumber.js';
function countDecimalPlaces(value) {
const number = Number(value);
@ -28,7 +29,11 @@ const separators = {
};
//分隔符换算
export function formatNumberWithSeparator(value, format = '0.00', step = 1, formatStyle?) {
if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {
return formatBigNumberWithSeparator(value, format, step, formatStyle);
}
let number = value;
if (formatStyle) {
number = Number(value);
}
@ -51,6 +56,33 @@ export function formatNumberWithSeparator(value, format = '0.00', step = 1, form
}
return formattedNumber;
}
//大字段分隔符换算
function formatBigNumberWithSeparator(value, format = '0.00', step = 1, formatStyle?) {
let number = value;
if (formatStyle) {
number = new BigNumber(value).toString();
}
let formattedNumber = '';
if (separators[format]) {
const { thousands, decimal } = separators[format];
const [integerPart, initFractionalPart] = number.toString().split('.');
let fractionalPart = initFractionalPart;
// 格式化整数部分
const formattedIntegerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousands);
// 处理小数部分
if (fractionalPart && step) {
fractionalPart = fractionalPart.substring(0, step);
formattedNumber = `${formattedIntegerPart}${decimal}${fractionalPart}`;
} else {
formattedNumber = formattedIntegerPart;
}
} else {
formattedNumber = number.toString();
}
return formattedNumber;
}
//单位换算
export function formatUnitConversion(value, operator = '*', multiplier?: number) {
@ -96,7 +128,7 @@ export function scientificNotation(number, decimalPlaces, separator = '.') {
}
export function formatNumber(props) {
const { step, formatStyle = 'normal', value, unitConversion, unitConversionType, separator = '0.00' } = props;
const { step, formatStyle = 'normal', value, unitConversion, unitConversionType, separator = '0,0.00' } = props;
if (!isValid(value)) {
return null;

View File

@ -9,7 +9,7 @@
import { fireEvent, render, screen } from '@nocobase/test/client';
import React from 'react';
import { formatNumberWithSeparator, formatUnitConversion, scientificNotation } from '../ReadPretty';
import { formatNumberWithSeparator, formatUnitConversion, scientificNotation, formatNumber } from '../ReadPretty';
import App2 from '../demos/addonBefore&addonAfter';
import App3 from '../demos/highPrecisionDecimals';
import App1 from '../demos/inputNumber';
@ -126,6 +126,21 @@ describe('ReadPretty:formatUnitConversion', () => {
});
});
describe('ReadPretty:MAX_SAFE_INTEGER', () => {
test('value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER', () => {
const result = formatNumber({
value: '1691195350092210177',
formatStyle: 'normal',
step: 1,
});
expect(result).toBe('1,691,195,350,092,210,177');
});
test('normal value', () => {
const result = formatNumber({ value: 3, formatStyle: 'normal', step: 1 });
expect(result).toBe('3');
});
});
describe('ReadPretty:scientificNotation', () => {
// Test case 1: Format a number into scientific notation with 2 decimal places
test('Format number into scientific notation', () => {

View File

@ -135,7 +135,7 @@ test.describe('form item & view form', () => {
await expect(
page
.getByLabel('block-item-CollectionField-general-form-general.integer-integer')
.getByText(record.integer.toFixed(0)),
.getByText(record.integer.toLocaleString()),
).toBeVisible();
await expect(
page
@ -145,7 +145,7 @@ test.describe('form item & view form', () => {
await expect(
page
.getByLabel('block-item-CollectionField-general-form-general.percent-percent')
.getByText(`${(record.percent * 100).toFixed(0)}%`),
.getByText(`${Math.round(record.percent * 100).toLocaleString()}%`),
).toBeVisible();
await expect(
page
@ -195,9 +195,11 @@ test.describe('table column & table', () => {
expectValue: async () => {
await expect(page.getByRole('button', { name: record.email })).toBeVisible();
await expect(page.getByRole('button', { name: record.singleLineText })).toBeVisible();
await expect(page.getByRole('button', { name: String(record.integer) })).toBeVisible();
await expect(page.getByRole('button', { name: record.integer.toLocaleString() })).toBeVisible();
await expect(page.getByRole('button', { name: record.number.toFixed(0) })).toBeVisible();
await expect(page.getByRole('button', { name: `${(record.percent * 100).toFixed(0)}%` })).toBeVisible();
await expect(
page.getByRole('button', { name: `${Math.round(record.percent * 100).toLocaleString()}%` }),
).toBeVisible();
await expect(page.getByRole('button', { name: record.longText.slice(0, 10) })).toBeVisible();
},
});

View File

@ -125,7 +125,7 @@ test.describe('form item & create form', () => {
page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'),
).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.integer-integer')).toHaveText(
'integer:112233',
'integer:112,233',
);
},
});
@ -223,7 +223,7 @@ test.describe('form item & edit form', () => {
page.getByLabel('block-item-CollectionField-general-form-general.integer-integer').getByRole('spinbutton'),
).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.integer-integer')).toHaveText(
`integer:${record.integer}`,
`integer:${record.integer.toLocaleString()}`,
);
},
});