/** * 浓度单位转换 (同一类别内转换) */ class ConcentrationConverter { // 单位换算系数 unitFactors = { // 质量单位(以g为基准) 'g': 1, 'mg': 1e-3, 'μg': 1e-6, 'ug': 1e-6, // μg的别名 'ng': 1e-9, 'pg': 1e-12, 'fg': 1e-15, // 体积单位(以L为基准) 'L': 1, 'mL': 1e-3, 'μL': 1e-6, 'uL': 1e-6, // μL的别名 'nL': 1e-9, 'pL': 1e-12, 'fL': 1e-15, // 摩尔单位(以mol为基准) 'mol': 1, 'mmol': 1e-3, 'μmol': 1e-6, 'umol': 1e-6, // μmol的别名 'nmol': 1e-9, 'pmol': 1e-12, 'fmol': 1e-15, // 活性单位(以U为基准) 'U': 1, 'IU': 1, // 假设1 IU = 1 U 'mU': 1e-3, 'mIU': 1e-3, }; // 支持的浓度单位(按类别分组) unitCategories = { 'mass': ['mg/mL', 'μg/mL', 'ug/mL', 'ng/mL', 'pg/mL', 'fg/mL', 'g/L', 'mg/L', 'μg/L'], 'mole': ['mol/mL', 'mol/L', 'mmol/L', 'μmol/L', 'umol/L', 'nmol/L', 'pmol/L', 'mmol/mL', 'μmol/mL'], 'activity': ['U/mL', 'IU/mL', 'U/L', 'IU/L'], 'percent': ['%'] }; /** * 规范化单位(统一别名) */ normalizeUnit(unit) { const aliasMap = { 'ug/mL': 'μg/mL', 'umol/L': 'μmol/L', 'uL': 'μL', 'ul': 'μL', 'IU/mL': 'U/mL', 'IU/L': 'U/L' }; return aliasMap[unit] || unit; } /** * 获取单位类别 */ getUnitCategory(unit) { const normalizedUnit = this.normalizeUnit(unit); for (const [category, units] of Object.entries(this.unitCategories)) { if (units.includes(normalizedUnit)) { return category; } } throw new Error(`不支持的浓度单位: ${unit}`); } /** * 检查两个单位是否属于同一类别 */ isSameCategory(unit1, unit2) { try { const cat1 = this.getUnitCategory(unit1); const cat2 = this.getUnitCategory(unit2); return cat1 === cat2; } catch { return false; } } /** * 浓度单位转换(核心方法) * @param {number|string} value - 待转换的值 * @param {string} targetUnit - 目标单位 * @returns {number} 转换后的值 */ convert(value, targetUnit) { // 1. 解析输入值 let inputValue, inputUnit; if (typeof value === 'string') { const match = value.toString().trim().match(/^([\d.]+(?:[eE][+-]?\d+)?)(?:\s*([a-zA-Zμ/%]+))?$/); if (!match) { throw new Error(`输入格式错误: ${value}`); } inputValue = parseFloat(match[1]); inputUnit = match[2] ? this.normalizeUnit(match[2]) : ''; } else if (typeof value === 'number') { inputValue = value; inputUnit = ''; // 无量纲 } else { throw new Error('输入值必须是数字或字符串'); } const normalizedTargetUnit = this.normalizeUnit(targetUnit); // 2. 检查是否需要转换 if (!inputUnit) { return inputValue; // 无量纲输入,直接返回 } if (inputUnit === normalizedTargetUnit) { return inputValue; // 相同单位,直接返回 } // 3. 检查是否为%单位 if (inputUnit === '%' || normalizedTargetUnit === '%') { // %单位是单独的系列,不进行转换 throw new Error(`单位类别不匹配: ${inputUnit} 不能转换为 ${targetUnit}`); } // 4. 验证单位类别 if (!this.isSameCategory(inputUnit, normalizedTargetUnit)) { throw new Error(`单位类别不匹配: ${inputUnit} 不能转换为 ${targetUnit}`); } // 5. 执行转换 return this._convertValue(inputValue, inputUnit, normalizedTargetUnit); } /** * 内部转换逻辑 */ _convertValue(value, fromUnit, toUnit) { // 解析浓度单位:分子/分母 const [fromNum, fromDen] = fromUnit.split('/'); const [toNum, toDen] = toUnit.split('/'); // 获取各部分的换算系数 const numFactor = this.unitFactors[fromNum] / this.unitFactors[toNum]; const denFactor = this.unitFactors[toDen] / this.unitFactors[fromDen]; // 计算总转换系数 return value * numFactor * denFactor; } /** * 批量转换 */ convertAll(values, targetUnit) { if (!Array.isArray(values)) { throw new Error('输入必须是数组'); } return values.map(value => this.convert(value, targetUnit)); } /** * 验证单位是否支持 */ isSupportedUnit(unit) { try { this.getUnitCategory(unit); return true; } catch { return false; } } } export const convertConcentration = new ConcentrationConverter();