|
|
- /**
- * 体积单位转换
- * 支持的体积单位:pL, nL, uL (μL), mL, L
- */
-
- class VolumeConverter {
- // 体积单位换算系数(以升L为基准)
- unitFactors = {
- 'L': 1,
- 'mL': 1e-3, // 毫升
- 'μL': 1e-6, // 微升
- 'uL': 1e-6, // 微升(别名)
- 'nL': 1e-9, // 纳升
- 'pL': 1e-12 // 皮升
- };
-
- // 支持的单位列表
- supportedUnits = ['L', 'mL', 'μL', 'uL', 'nL', 'pL'];
-
- /**
- * 规范化单位(统一别名)
- */
- normalizeUnit(unit) {
- const aliasMap = {
- 'ul': 'uL',
- 'Ul': 'uL',
- 'UL': 'uL',
- 'μl': 'μL',
- 'Μl': 'μL',
- 'ΜL': 'μL'
- };
-
- // 转换为标准形式
- let normalized = unit;
-
- // 处理μ符号的各种表示
- if (unit.toLowerCase() === 'ul' || unit === 'μL' || unit === 'uL') {
- normalized = 'μL';
- }
- // 其他别名处理
- else if (aliasMap[unit]) {
- normalized = aliasMap[unit];
- }
-
- return normalized;
- }
-
- /**
- * 验证单位是否支持
- */
- isSupportedUnit(unit) {
- const normalizedUnit = this.normalizeUnit(unit);
- return this.supportedUnits.includes(normalizedUnit);
- }
-
- /**
- * 获取所有支持的单位
- */
- getSupportedUnits() {
- return [...this.supportedUnits];
- }
-
- /**
- * 体积单位转换(核心方法)
- * @param {number|string} value - 待转换的值
- * @param {string} targetUnit - 目标单位
- * @returns {number} 转换后的值
- */
- convert(value, targetUnit) {
- // 1. 解析输入值
- let inputValue, inputUnit;
-
- if (typeof value === 'string') {
- const result = this.parseValue(value);
- inputValue = result.value;
- inputUnit = result.unit;
- } else if (typeof value === 'number') {
- inputValue = value;
- inputUnit = ''; // 无量纲
- } else {
- throw new Error('输入值必须是数字或字符串');
- }
-
- const normalizedTargetUnit = this.normalizeUnit(targetUnit);
-
- // 2. 验证目标单位
- if (!this.isSupportedUnit(normalizedTargetUnit)) {
- throw new Error(`不支持的单位: ${targetUnit}。支持的单位: ${this.supportedUnits.join(', ')}`);
- }
-
- // 3. 检查是否需要转换
- if (!inputUnit) {
- return inputValue; // 无量纲输入,直接返回
- }
-
- if (inputUnit === normalizedTargetUnit) {
- return inputValue; // 相同单位,直接返回
- }
-
- // 4. 执行转换
- return this._convertValue(inputValue, inputUnit, normalizedTargetUnit);
- }
-
- /**
- * 解析带单位的数值字符串
- */
- parseValue(valueStr) {
- const str = valueStr.toString().trim();
-
- // 支持科学计数法
- const match = str.match(/^([+-]?\d*\.?\d+(?:[eE][+-]?\d+)?)\s*([a-zA-Zμ]+)$/);
-
- if (!match) {
- throw new Error(`格式错误: ${valueStr}。正确格式如: "10mL", "5.5μL", "1.23e-6L"`);
- }
-
- const value = parseFloat(match[1]);
- const rawUnit = match[2];
- const unit = this.normalizeUnit(rawUnit);
-
- // 验证单位是否支持
- if (!this.isSupportedUnit(unit)) {
- throw new Error(`不支持的单位: ${rawUnit}。支持的单位: ${this.supportedUnits.join(', ')}`);
- }
-
- return { value, unit };
- }
-
- /**
- * 内部转换逻辑
- */
- _convertValue(value, fromUnit, toUnit) {
- // 统一处理μL的多种表示
- const normalizedFromUnit = this.normalizeUnit(fromUnit);
- const normalizedToUnit = this.normalizeUnit(toUnit);
-
- // 获取换算系数
- const fromFactor = this.unitFactors[normalizedFromUnit];
- const toFactor = this.unitFactors[normalizedToUnit];
-
- if (fromFactor === undefined || toFactor === undefined) {
- throw new Error(`单位换算系数未定义: ${fromUnit} 或 ${toUnit}`);
- }
-
- // 转换公式:value * (fromFactor / toFactor)
- return value * (fromFactor / toFactor);
- }
-
- /**
- * 批量转换
- */
- convertAll(values, targetUnit) {
- if (!Array.isArray(values)) {
- throw new Error('输入必须是数组');
- }
-
- return values.map(value => this.convert(value, targetUnit));
- }
-
- /**
- * 格式化输出
- */
- format(value, unit, precision = 6) {
- const numValue = typeof value === 'string' ? parseFloat(value) : value;
-
- if (isNaN(numValue)) {
- return 'NaN';
- }
-
- // 根据数值大小选择合适的显示格式
- const absValue = Math.abs(numValue);
-
- if (absValue === 0) {
- return `0 ${unit}`;
- }
-
- if (absValue < 0.001 || absValue >= 1000000) {
- return `${numValue.toExponential(precision)} ${unit}`;
- }
-
- // 确定小数位数
- let decimalPlaces = precision;
- if (absValue < 1) {
- decimalPlaces = Math.max(precision, Math.ceil(-Math.log10(absValue)) + 2);
- } else if (absValue >= 100) {
- decimalPlaces = Math.max(0, precision - 2);
- }
-
- return `${numValue.toFixed(decimalPlaces)} ${unit}`;
- }
-
- /**
- * 获取单位换算关系
- */
- getConversionFactor(fromUnit, toUnit) {
- const normalizedFromUnit = this.normalizeUnit(fromUnit);
- const normalizedToUnit = this.normalizeUnit(toUnit);
-
- if (!this.isSupportedUnit(normalizedFromUnit) || !this.isSupportedUnit(normalizedToUnit)) {
- throw new Error('单位不支持');
- }
-
- const fromFactor = this.unitFactors[normalizedFromUnit];
- const toFactor = this.unitFactors[normalizedToUnit];
-
- return fromFactor / toFactor;
- }
-
- /**
- * 创建快捷转换方法
- */
- createShortcutMethods() {``
- const shortcuts = {};
-
- this.supportedUnits.forEach(unit => {
- const methodName = `to${unit.replace('μ', 'u')}`;
- shortcuts[methodName] = (value) => this.convert(value, unit);
- });
-
- return shortcuts;
- }
- }
- export const volumeConverter = new VolumeConverter();
|