diff --git a/docs/content/components/usage-bar.mdx b/docs/content/components/usage-bar.mdx index f0bb3675..bac48f5b 100644 --- a/docs/content/components/usage-bar.mdx +++ b/docs/content/components/usage-bar.mdx @@ -19,6 +19,8 @@ date: 2019-06-06 ```
+ + diff --git a/src/components/UsageBar/index.tsx b/src/components/UsageBar/index.tsx index 4d77c2e2..4635c93f 100644 --- a/src/components/UsageBar/index.tsx +++ b/src/components/UsageBar/index.tsx @@ -36,6 +36,7 @@ const UsageBar: React.FC = props => { hideRight, showZeroMax, withUnavailable, + formatType, } = props; const hasNow = props.hasOwnProperty('now'); const hasPercent = props.hasOwnProperty('percent'); @@ -44,8 +45,8 @@ const UsageBar: React.FC = props => { const errorPercent = props.unavailableData && max && props.unavailableData / max; let nowValue: number | string | undefined = now; let maxValue: number | string | undefined = max; - let nowSuffix = ''; - let maxSuffix = ''; + let nowSuffix: any = ''; + let maxSuffix: any = ''; let left; let right; let bsStyle; @@ -57,14 +58,19 @@ const UsageBar: React.FC = props => { nowSuffix = maxSuffix = '%'; } - if (isByte) { + if (isByte || formatType) { // hasPercent 表明左边数据设置完成(百分比形式),不需要再调整 + let byteOptions: object = { splitUnit: true }; + if (formatType) { + byteOptions = { splitUnit: true, formatType }; + } + if (!hasPercent && now) { - const nowArr: any = xbytes(now, { splitUnit: true }); + const nowArr: any = xbytes(now, byteOptions); nowValue = nowArr[0]; nowSuffix = nowArr[1]; } - const maxArr: any = max && xbytes(max, { splitUnit: true }); + const maxArr: any = max && xbytes(max, byteOptions); maxValue = maxArr[0]; maxSuffix = maxArr[1]; } else if (isBulk) { @@ -155,6 +161,10 @@ UsageBar.propTypes = { * 数字以字节(B, KB, MB, GB...)为单位展示 **/ isByte: PropTypes.bool, + /** + * 格式化输出,可选[decimal|binary] + **/ + formatType: PropTypes.string, /** * 数字以数量(万, 亿, 兆, 京...)为单位展示 **/ diff --git a/src/interface.tsx b/src/interface.tsx index 1a8f500b..8f3f857b 100644 --- a/src/interface.tsx +++ b/src/interface.tsx @@ -90,6 +90,7 @@ export interface UsageBarProps { hideRight?: boolean; showZeroMax?: boolean; withUnavailable?: boolean; + formatType?: string; } export interface LoaderProps { diff --git a/src/utils/bulk.ts b/src/utils/bulk.ts index 17c68883..00171dd4 100644 --- a/src/utils/bulk.ts +++ b/src/utils/bulk.ts @@ -40,7 +40,7 @@ export default function bulk(value: number, options: OPTIONS, locale?: LocaleTyp i++; } unit = BULK[i - 1][1]; - let resultValue: any = value / (BULK[i - 1][0] as number); + let resultValue: number = value / +BULK[i - 1][0]; if (parseInt(String(resultValue), 10) !== resultValue) { resultValue = Number(resultValue.toFixed(2)); } diff --git a/src/utils/xbytes.ts b/src/utils/xbytes.ts index 4eb82c00..2d21d155 100644 --- a/src/utils/xbytes.ts +++ b/src/utils/xbytes.ts @@ -1,17 +1,22 @@ interface OPTIONS { - unitSeparator?: boolean - decimalPlaces?: number - fixedDecimals?: boolean - toUnit?: string - withoutFloat?: boolean - splitUnit?: boolean - thousandsSeparator?: string + formatType?: string; + unitSeparator?: boolean; + decimalPlaces?: number; + fixedDecimals?: boolean; + toUnit?: string; + withoutFloat?: boolean; + splitUnit?: boolean; + thousandsSeparator?: string; +} + +type Map = { + [key: string] : number; } const formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; const formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; -const map = { +const basicMap = { b: 1, kb: 1 << 10, mb: 1 << 20, @@ -22,19 +27,55 @@ const map = { zb: (1 << 30) * Math.pow(1024, 4), }; +const binaryMap= { + b: 1, + kib: 1 << 10, + mib: 1 << 20, + gib: 1 << 30, + tib: (1 << 30) * 1024, + pib: (1 << 30) * Math.pow(1024, 2), + eib: (1 << 30) * Math.pow(1024, 3), + zib: (1 << 30) * Math.pow(1024, 4), +}; + +const decimal = 1000; +const decimalMap = { + b: 1, + kb: Math.pow(decimal, 1), + mb: Math.pow(decimal, 2), + gb: Math.pow(decimal, 3), + tb: Math.pow(decimal, 4), + pb: Math.pow(decimal, 5), + eb: Math.pow(decimal, 6), + zb: Math.pow(decimal, 7), +}; + const numberIsFinite = Number.isFinite || (v => typeof v === 'number' && isFinite(v)); // 原正则 https://www.npmjs.com/package/bytes (存在bug:当传入 '1.2345678901234568e+29GB'字符串进行转换时,结果为 1) // const parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb|eb|zb)$/i; // 2018-12-19 兼容科学计数法: 1.2345678901234568e+29 -const parseRegExp = /^((-|\+)?(\d+(?:\.\d*[Ee+-]*\d+)?)) *(kb|mb|gb|tb|pb|eb|zb)$/i; +const basicParseRegExp = /^((-|\+)?(\d+(?:\.\d*[Ee+-]*\d+)?)) *(kb|mb|gb|tb|pb|eb|zb)$/i; +const decimalParseRegExp = basicParseRegExp; +const binaryParseRegExp = /^((-|\+)?(\d+(?:\.\d*[Ee+-]*\d+)?)) *(kib|mib|gib|tib|pib|eib|zib)$/i; function format(value: number, options: OPTIONS) { if (!numberIsFinite(value)) { return null; } + let map: Map = basicMap; + if (options && options.formatType) { + if (options.formatType === 'decimal') { + map = decimalMap; + } + + if (options.formatType === 'binary') { + map = binaryMap; + } + } + const mag = Math.abs(value); const thousandsSeparator = options && options.thousandsSeparator ? options.thousandsSeparator : ''; @@ -82,10 +123,10 @@ function format(value: number, options: OPTIONS) { if (!isNaN(Number(str))) str = Number(str); return [str, unit.toUpperCase()]; } - return str + unitSeparator + unit.toUpperCase(); + return str + unitSeparator + unit.toUpperCase().replace('I','i'); } -function parse(val: string) { +function parse(val: string, options: OPTIONS) { if (typeof val === 'number' && !isNaN(val)) { return val; } @@ -94,6 +135,21 @@ function parse(val: string) { return null; } + let parseRegExp = basicParseRegExp; + let map: Map = basicMap; + + if (options && options.formatType) { + if (options.formatType === 'decimal') { + map = decimalMap; + parseRegExp = decimalParseRegExp; + } + + if (options.formatType === 'binary') { + map = binaryMap; + parseRegExp = binaryParseRegExp; + } + } + const results = parseRegExp.exec(val); let floatValue; let unit = 'b'; @@ -111,7 +167,7 @@ function parse(val: string) { export default function xbytes(value: number | string, options: OPTIONS) { if (typeof value === 'string') { - return parse(value); + return parse(value, options); } if (typeof value === 'number') {