fix: InputNumber组件初始值未按照精度处理问题 (#5226)

This commit is contained in:
RUNZE LU 2022-08-25 13:55:15 +08:00 committed by GitHub
parent 98d0d213bc
commit 6d00e12423
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 242 additions and 10 deletions

View File

@ -24,6 +24,37 @@ order: 32
}
```
## 设置精度
`precision` 设置数字的显示精度,一般需要配合`step`属性使用,以实现细粒度调整。
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"data": {
"number2": 3.1234
},
"body": [
{
"type": "input-number",
"name": "number1",
"label": "数字",
"precision": 2,
"step": 0.01,
"value": 2.98786
},
{
"type": "input-number",
"name": "number2",
"label": "数字2",
"precision": 3,
"step": 0.001
}
]
}
```
## 前后缀、千分分隔
```schema: scope="body"

View File

@ -104,7 +104,7 @@ export class NumberInput extends React.Component<NumberProps, any> {
}
const target = getMiniDecimal(val).add(stepDecimal.toString());
const getPrecision = (numStr: string) => {
if (precision! >= 0) {
if (precision != null && precision >= 0) {
return precision;
}
return Math.max(

View File

@ -459,6 +459,165 @@ exports[`Renderer:number with borderMode 2`] = `
</div>
`;
exports[`Renderer:number with precision and default value 1`] = `
<div>
<div
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
style="position: relative;"
>
<div
class="cxd-Panel-heading"
>
<h3
class="cxd-Panel-title"
>
<span
class="cxd-TplField"
>
<span>
表单
</span>
</span>
</h3>
</div>
<div
class="cxd-Panel-body"
>
<form
class="cxd-Form cxd-Form--normal"
novalidate=""
>
<input
style="display: none;"
type="submit"
/>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
number
</span>
</span>
</span>
</label>
<div
class="cxd-NumberControl cxd-Form-control"
>
<div
class="cxd-Number cxd-Number--borderFull"
>
<div
class="cxd-Number-handler-wrap"
>
<span
aria-disabled="false"
aria-label="Increase Value"
class="cxd-Number-handler cxd-Number-handler-up"
role="button"
unselectable="on"
>
<span
class="cxd-Number-handler-up-inner"
unselectable="on"
/>
</span>
<span
aria-disabled="false"
aria-label="Decrease Value"
class="cxd-Number-handler cxd-Number-handler-down"
role="button"
unselectable="on"
>
<span
class="cxd-Number-handler-down-inner"
unselectable="on"
/>
</span>
</div>
<div
class="cxd-Number-input-wrap"
>
<input
aria-valuenow="2.99"
autocomplete="off"
class="cxd-Number-input"
role="spinbutton"
step="0.01"
value="2.99"
/>
</div>
</div>
</div>
</div>
</form>
</div>
<div
class="cxd-Panel-footerWrap"
>
<div
class="cxd-Panel-btnToolbar cxd-Panel-footer"
>
<button
class="cxd-Button cxd-Button--primary"
type="submit"
>
<span>
提交
</span>
</button>
</div>
</div>
<div
class="resize-sensor"
style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
class="resize-sensor-expand"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0px; top: 0px; width: 10px; height: 10px;"
/>
</div>
<div
class="resize-sensor-shrink"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0; top: 0; width: 200%; height: 200%"
/>
</div>
<div
class="resize-sensor-appear"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;animation-name: apearSensor; animation-duration: 0.2s;"
/>
</div>
</div>
</div>
`;
exports[`Renderer:number with prefix & suffix & kilobitSeparator 1`] = `
<div>
<div

View File

@ -1,4 +1,15 @@
import React = require('react');
/**
* InputNumber
*
* 1.
* 2. &
* 3. &
* 4.
* 5.
* 6.
* 7. &
*/
import {render, fireEvent, waitFor} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
@ -169,6 +180,17 @@ test('Renderer:number with unitOptions', async () => {
expect(container).toMatchSnapshot();
});
test('Renderer:number with precision and default value', async () => {
const {input, wrap, container, getByText} = await setup({
precision: 2,
step: 0.01,
value: 2.98786
});
expect(input.value).toBe('2.99');
expect(container).toMatchSnapshot();
});
test('Renderer:number with step & precision & displayMode & keyboard', async () => {
const {input, wrap, container, getByText} = await setup({
step: 3,

View File

@ -1,12 +1,19 @@
import React from 'react';
import {FormItem, FormControlProps, FormBaseControl} from 'amis-core';
import {toFixed} from 'rc-input-number/lib/utils/MiniDecimal';
import {FormItem, FormControlProps} from 'amis-core';
import cx from 'classnames';
import {filter} from 'amis-core';
import {NumberInput, Select} from 'amis-ui';
import {autobind, createObject} from 'amis-core';
import {normalizeOptions, Option} from 'amis-core';
import {PlainObject, ActionObject} from 'amis-core';
import {BaseSchema, FormBaseControlSchema} from '../../Schema';
import {
filter,
autobind,
createObject,
normalizeOptions,
Option,
PlainObject,
ActionObject
} from 'amis-core';
import {FormBaseControlSchema} from '../../Schema';
/**
*
* https://baidu.gitee.io/amis/docs/components/form/number
@ -131,10 +138,25 @@ export default class NumberControl extends React.Component<
constructor(props: NumberProps) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleChangeUnit = this.handleChangeUnit.bind(this);
const unit = this.getUnit();
const unitOptions = normalizeOptions(props.unitOptions);
const {formItem, setPrinstineValue, precision, value} = props;
const normalizedPrecision = this.filterNum(precision);
/** 如果设置了precision需要处理入参value的精度 */
if (formItem && value != null && normalizedPrecision != null) {
const normalizedValue = toFixed(
value.toString(),
'.',
normalizedPrecision
);
setPrinstineValue(parseFloat(normalizedValue));
}
this.state = {unit, unitOptions};
}
@ -282,9 +304,7 @@ export default class NumberControl extends React.Component<
keyboard,
displayMode
} = this.props;
let precisionProps: any = {};
const finalPrecision = this.filterNum(precision);
if (typeof finalPrecision === 'number') {
precisionProps.precision = finalPrecision;