华西海圻ELN前端工程
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

182 lines
4.6 KiB

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