const { formatMagnitudeNumber, getOption, normalizeIndex, parseLooseNumber, selectBestUnit } = require('../calculator-helpers.js') const MODE_OPTIONS = [ { key: 'water', label: '水侧冷量' }, { key: 'airSensible', label: '风侧显热' }, { key: 'airEnthalpy', label: '风侧焓差' }, { key: 'cop', label: 'COP' }, { key: 'carnot', label: '卡诺COP' }, { key: 'temperature', label: '过热过冷' } ] const FIELD_GROUPS = { airEnthalpy: [ { key: 'coolingAirFlow', label: '风量', unit: 'm³/h', placeholder: '3000' }, { key: 'coolingAirInletEnthalpy', label: '入口焓值', unit: 'kJ/kg', placeholder: '58' }, { key: 'coolingAirOutletEnthalpy', label: '出口焓值', unit: 'kJ/kg', placeholder: '42' } ], airSensible: [ { key: 'coolingAirFlow', label: '风量', unit: 'm³/h', placeholder: '3000' }, { key: 'coolingAirInletTemp', label: '入口温度', unit: '°C', placeholder: '27' }, { key: 'coolingAirOutletTemp', label: '出口温度', unit: '°C', placeholder: '15' } ], carnot: [ { key: 'coolingEvapTemp', label: '蒸发温度', unit: '°C', placeholder: '0' }, { key: 'coolingCondTemp', label: '冷凝温度', unit: '°C', placeholder: '40' } ], cop: [ { key: 'coolingCapacity', label: '制冷量', unit: 'kW', placeholder: '10' }, { key: 'coolingInputPower', label: '输入功率', unit: 'kW', placeholder: '2.5' } ], temperature: [ { key: 'coolingSuctionTemp', label: '吸气温度', unit: '°C', placeholder: '8' }, { key: 'coolingEvapTemp', label: '蒸发饱和温度', unit: '°C', placeholder: '2' }, { key: 'coolingCondTemp', label: '冷凝饱和温度', unit: '°C', placeholder: '45' }, { key: 'coolingLiquidTemp', label: '液管温度', unit: '°C', placeholder: '39' } ], water: [ { key: 'coolingWaterFlow', label: '水流量', unit: 'm³/h', placeholder: '10' }, { key: 'coolingWaterInlet', label: '入口温度', unit: '°C', placeholder: '12' }, { key: 'coolingWaterOutlet', label: '出口温度', unit: '°C', placeholder: '7' } ] } const FORMULA_TEXT = { airEnthalpy: 'Q = 风量 × Δh / 3000', airSensible: 'Q = 0.000335 × 风量 × ΔT', carnot: 'COP = Te(K) / (Tc(K) - Te(K))', cop: 'COP = 制冷量 / 输入功率', temperature: '过热度 = 吸气 - 蒸发饱和,过冷度 = 冷凝饱和 - 液管', water: 'Q = 1.163 × 水流量 × ΔT' } const POWER_UNITS = [ { label: 'W', factor: 0.001 }, { label: 'kW', factor: 1 }, { label: 'MW', factor: 1000 } ] const COOLING_FORMAT_STEPS = [ { min: 1000, decimals: 2 }, { min: 1, decimals: 3 }, { min: 0.001, decimals: 5 }, { min: 0, decimals: 8 } ] const COOLING_VALUE_KEYS = [ 'coolingAirFlow', 'coolingAirInletEnthalpy', 'coolingAirInletTemp', 'coolingAirOutletEnthalpy', 'coolingAirOutletTemp', 'coolingCapacity', 'coolingCondTemp', 'coolingEvapTemp', 'coolingInputPower', 'coolingLiquidTemp', 'coolingSuctionTemp', 'coolingWaterFlow', 'coolingWaterInlet', 'coolingWaterOutlet' ] function formatNumber(value) { return formatMagnitudeNumber(value, { fallbackText: '--', steps: COOLING_FORMAT_STEPS }) } function formatPower(kwValue) { const unit = selectBestUnit(POWER_UNITS, kwValue, 1).unit return `${formatNumber(kwValue / unit.factor)} ${unit.label}` } function makeRow(label, value, unit = '') { return { label, value: unit ? `${formatNumber(value)} ${unit}` : formatNumber(value) } } function hasAll(values, keys) { return keys.every((key) => Number.isFinite(values[key])) } function calculate(modeKey, values) { if (Object.keys(values).some((key) => Number.isNaN(values[key]))) { return { errorText: '输入值格式无效', resultRows: [] } } if (modeKey === 'water') { if (!hasAll(values, ['coolingWaterFlow', 'coolingWaterInlet', 'coolingWaterOutlet'])) return { errorText: '', resultRows: [] } if (values.coolingWaterFlow < 0) return { errorText: '流量不能为负数', resultRows: [] } const deltaT = Math.abs(values.coolingWaterInlet - values.coolingWaterOutlet) const capacityKw = 1.163 * values.coolingWaterFlow * deltaT return { errorText: '', resultRows: [ { label: '冷量', value: formatPower(capacityKw) }, makeRow('温差', deltaT, '°C'), makeRow('冷吨', capacityKw / 3.517, 'RT') ] } } if (modeKey === 'airSensible') { if (!hasAll(values, ['coolingAirFlow', 'coolingAirInletTemp', 'coolingAirOutletTemp'])) return { errorText: '', resultRows: [] } if (values.coolingAirFlow < 0) return { errorText: '风量不能为负数', resultRows: [] } const deltaT = Math.abs(values.coolingAirInletTemp - values.coolingAirOutletTemp) const capacityKw = 0.000335 * values.coolingAirFlow * deltaT return { errorText: '', resultRows: [ { label: '显热冷量', value: formatPower(capacityKw) }, makeRow('温差', deltaT, '°C'), makeRow('冷吨', capacityKw / 3.517, 'RT') ] } } if (modeKey === 'airEnthalpy') { if (!hasAll(values, ['coolingAirFlow', 'coolingAirInletEnthalpy', 'coolingAirOutletEnthalpy'])) return { errorText: '', resultRows: [] } if (values.coolingAirFlow < 0) return { errorText: '风量不能为负数', resultRows: [] } const deltaH = Math.abs(values.coolingAirInletEnthalpy - values.coolingAirOutletEnthalpy) const capacityKw = values.coolingAirFlow * deltaH / 3000 return { errorText: '', resultRows: [ { label: '总冷量', value: formatPower(capacityKw) }, makeRow('焓差', deltaH, 'kJ/kg'), makeRow('冷吨', capacityKw / 3.517, 'RT') ] } } if (modeKey === 'cop') { if (!hasAll(values, ['coolingCapacity', 'coolingInputPower'])) return { errorText: '', resultRows: [] } if (values.coolingCapacity < 0 || values.coolingInputPower <= 0) return { errorText: '制冷量需大于等于0,输入功率需大于0', resultRows: [] } const cop = values.coolingCapacity / values.coolingInputPower return { errorText: '', resultRows: [ makeRow('COP', cop), makeRow('EER', cop * 3.412), { label: '制冷量', value: formatPower(values.coolingCapacity) } ] } } if (modeKey === 'carnot') { if (!hasAll(values, ['coolingEvapTemp', 'coolingCondTemp'])) return { errorText: '', resultRows: [] } const evapK = values.coolingEvapTemp + 273.15 const condK = values.coolingCondTemp + 273.15 if (evapK <= 0 || condK <= evapK) return { errorText: '冷凝温度需高于蒸发温度,且绝对温度需大于0K', resultRows: [] } const coolingCop = evapK / (condK - evapK) const heatingCop = condK / (condK - evapK) return { errorText: '', resultRows: [ makeRow('制冷COP', coolingCop), makeRow('制热COP', heatingCop), makeRow('温差', values.coolingCondTemp - values.coolingEvapTemp, '°C') ] } } if (modeKey === 'temperature') { if (!hasAll(values, ['coolingSuctionTemp', 'coolingEvapTemp', 'coolingCondTemp', 'coolingLiquidTemp'])) return { errorText: '', resultRows: [] } return { errorText: '', resultRows: [ makeRow('过热度', values.coolingSuctionTemp - values.coolingEvapTemp, '°C'), makeRow('过冷度', values.coolingCondTemp - values.coolingLiquidTemp, '°C') ] } } return { errorText: '', resultRows: [] } } function buildState(source = {}) { const modeIndex = normalizeIndex(source.coolingModeIndex, MODE_OPTIONS, 0) const mode = getOption(MODE_OPTIONS, modeIndex) const rawValues = COOLING_VALUE_KEYS.reduce((result, key) => { result[key] = String(source[key] === undefined || source[key] === null ? '' : source[key]) return result }, {}) const values = COOLING_VALUE_KEYS.reduce((result, key) => { result[key] = parseLooseNumber(rawValues[key]) return result }, {}) const result = calculate(mode.key, values) const fieldRows = (FIELD_GROUPS[mode.key] || []).map((field) => ({ ...field, value: rawValues[field.key] })) return { ...rawValues, coolingAnyInput: COOLING_VALUE_KEYS.some((key) => rawValues[key].trim()), coolingErrorText: result.errorText, coolingFieldRows: fieldRows, coolingFormulaText: FORMULA_TEXT[mode.key] || '', coolingModeIndex: modeIndex, coolingModeKey: mode.key, coolingModeOptions: MODE_OPTIONS, coolingModeText: mode.label, coolingResultRows: result.resultRows } } function createInitialState() { return buildState({}) } function updateState(state, changedData = {}) { return buildState({ ...state, ...changedData }) } function clearInputs(state) { const changedData = COOLING_VALUE_KEYS.reduce((result, key) => { result[key] = '' return result }, {}) return updateState(state, changedData) } module.exports = { MODE_OPTIONS, clearInputs, createInitialState, updateState }