|
|
- /**
- * 浓度单位转换 (同一类别内转换)
- */
-
- 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();
|