import { create, all, number, pow } from 'mathjs' const math = create(all) math.config({ number: 'BigNumber', precision: 64 }) export { math } /* * 计算当前样品分析值*/ export function calcAnalysisValue(group) { try { for (const g of group) { for (const ele of g.fields) { if (!ele.formula || ele.formula == '') continue if (ele.valueTypeManual && ele.valueTypeManual == '1') continue let formula = ele.formula let formulas = formula.split('|') let formulaVal = '' let hasNullVal = false formulas.forEach(f => { let value = '' if (f.charAt(0) === 'p') { // let o = elementParamValueData.find((i) => 'p' + i.paramNo === f); let o = findFieldInGroup(f, group, 'p') value = o.value } else if (f.charAt(0) === 'e') { // let o = elementParamValueData.find((i) => 'e' + i.paramNo === f); let o = findFieldInGroup(f, group, 'e') value = o.value } else if (f.charAt(0) === '<' || f.charAt(0) === '>') { value = "'" + f + "'" } else { value = f } if (typeof value == 'undefined' || value == null) { hasNullVal = true return true } formulaVal += value }) if (hasNullVal) { ele.value = null continue } let v if (formulaVal.startsWith('Get')) { //计算公式为Get开头的,都是执行方法 v = eval(formulaVal) } else { v = math.evaluate(formulaVal).toString() v = isFinite(v) ? v.toString() : '' } ele.value = handleRoundFiveNumber(v, ele.dataType) } } } catch (error) { console.log(error) } } // 根据样品和配置列计算分析值 export function calcRowAnalysisValue(row, columnObj, dynamicsColumns) { if (!columnObj.paramNo) return for (let i = 0; i < dynamicsColumns.length; i++) { let curItem = dynamicsColumns[i] if (curItem.fieldIndex === columnObj.fieldIndex) continue let param = columnObj.fieldIndex.charAt(0) === 'p' ? 'p' + columnObj.paramNo : 'e' + columnObj.paramNo if (curItem.formula && curItem.formula.includes(param)) { let formula = curItem.formula let formulas = formula.split('|') let formulaVal = '' formulas.forEach(f => { if (f.charAt(0) === 'p') { let o = dynamicsColumns.find(i => 'p' + i.paramNo === f) formulaVal += row[o.fieldIndex]?.value ? row[o.fieldIndex].value : 0 } else if (f.charAt(0) === 'e') { let o = dynamicsColumns.find(i => 'e' + i.paramNo === f) formulaVal += row[o.fieldIndex]?.value ? row[o.fieldIndex].value : 0 } else { formulaVal += f } }) let v if (formulaVal.startsWith('Get')) { formulaVal = formulaVal.replace(')', ",'" + row.conBaseSampleId + "')") v = eval(formulaVal) } else { v = math.evaluate(formulaVal).toString() v = isFinite(v) ? v : 0 } row[curItem.fieldIndex].value = handleRoundFiveNumber(Number(v), row[curItem.fieldIndex].decimalPosition) calcRowAnalysisValue(row, curItem, dynamicsColumns) } } } const findFieldInGroup = function (paramNo, group, p) { for (const g of group) { for (const f of g.fields) { if (p + f.paramNo === paramNo) { return f } } } return { value: null } } const GetRecoveryRate = function (elementFormulaCode, value) { // //读取conRecoveryRateList const conRecoveryRateList = uni.getStorageSync('ConRecoveryRateList') if (!conRecoveryRateList) return let o = conRecoveryRateList.find(i => { //console.log("取得的" + i + "回收率:" + i); if (value === 0) { return i.elementFormulaCode === elementFormulaCode && i.minValue === value } return i.elementFormulaCode === elementFormulaCode && i.minValue < value && value <= i.maxValue }) // console.log(o); const rate = o ? o.rate : 100 // console.log("取得的" + elementFormulaCode + "回收率:" + rate); return rate // console.log("执行方法:GetRecoveryRate"); // return 100; } /* * 根据硫值计算:支持碳、硝酸钾(滇中) * 当S%<22%时,需加入淀粉的量=(75-S%*22*M)/12 * 当 S%>22%时,需加入硝酸钾的量=(S%*22*M-75)/4 * 当 S%==22%时,硝酸钾为0,淀粉为空 * sValueKey:硫值对应的dicKey * weightKey:重量对应的dicKey * percent:计算参数 * * 举例:Get_C_KNO3_bySValue|(|p14|, |p2|, |>|) * */ const Get_C_KNO3_bySValue = function (sValue, weight, operator) { //判断sValue是数字 if (isNaN(sValue) || isNaN(weight)) { return '' } let v = number(sValue) const w = number(weight) if (w === 0) return '' v = v * 0.01 //当S%<22%时,需加入淀粉的量=(75-S%*22*M)/12 if (operator === '<' && v < 0.22) { // return ( 75 - v * 22 * w )/12; return accDiv(accSub(75, accMul(accMul(v, 22), w)), 12) } //S%>22%时,需加入硝酸钾的量=(S%*22*M-75)/4 if (operator === '>=' && v >= 0.22) { //S%==22%时,硝酸钾为0,淀粉为空 if (v === 22) return 0 // return ( v * 22 * w - 75 ) + 44; return accDiv(accSub(accMul(v, accMul(22, w)), 75), 4) } return '' } /** 处理数值数据:四舍六入奇进偶不进 * 1,如果取小数的最后一位为5,5前为奇数进位,为偶不进,五后非零就进一,五后皆零看奇偶,五前为偶应舍去,五前为奇要进一 * 2.5后不为0时就入,为0时看5前,奇进偶不进 * 3.四舍,六入 * 传入数值和保留位数 */ export function handleRoundFiveNumber(number, fixed = 0) { if (number == null || number === '' || isNaN(number)) return number if (fixed === -1) return number number = String(number) //可以考虑清掉末尾的0,暂时限制了不会有,因为传入数值,末尾0是去掉的 const index = number.indexOf('.') if (index == -1) { if (fixed > 0) { number += '.' } for (let i = 0; i < fixed; i++) { number += '0' } //补0返回 return number } //取到保留小数位的下一位,5.5555取保留俩位,那就是小数点后第三位 const indexFixed = index + fixed + 1 if (indexFixed >= number.length) { //如果小数位数不够, 补0直接返回 const zerolen = indexFixed - number.length for (let i = 0; i < zerolen; i++) { number += '0' } return number } //取保留位数的后一位做判断,以下是有5的判断 const endNumber = number.substr(indexFixed, 1) if (endNumber != '5') { //如果做判断的数不是五,就按正常的四舍五入,即忽略了5,后面补0的那些由于是数字传进来,0已经去掉,此处不做处理 return Number(number).toFixed(fixed) } if (indexFixed != number.length - 1) { //由于当前判断位不是最后一位,而又去除了0,那么后面后的位数应该直接入位,五后不为0时入,由于会有小于五的,四舍五入肯定不行,那么只能截取到当前保留位数,然后转成数字加上10的负fixed的次方即可 number = number.substring(0, indexFixed) if (number.indexOf('-') != -1) { //需要考虑到负数的情况 return (Number(number) - Number(Math.pow(10, -fixed))).toFixed(fixed) } return (Number(number) + Number(Math.pow(10, -fixed))).toFixed(fixed) //return this.accAdd(number,Math.pow(10,-fixed)) } //接下来就时五后没有值也就是0的需要看前面的奇入偶不入了,取当前位的上一位 let twoNumber = number.substr(indexFixed - 1, 1) if (twoNumber == '.') { //取到小数点,再取一次,要取到小数点左边第一位 twoNumber = number.substr(indexFixed - 2, 1) } if ('13579'.indexOf(twoNumber) != -1) { //奇进 number = number.substring(0, indexFixed) if (number.indexOf('-') != -1) { //需要考虑到负数的情况 return (Number(number) - Math.pow(10, -fixed)).toFixed(fixed) } return (Number(number) + Math.pow(10, -fixed)).toFixed(fixed) } //偶不进,将取值的当前位数,直接截取字符即可 return number.substr(0, indexFixed) } /** ** 除法函数,用来得到精确的除法结果 ** 说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。 ** 调用:accDiv(arg1,arg2) ** 返回值:arg1除以arg2的精确结果 **/ function accDiv(arg1, arg2) { var t1 = 0, t2 = 0, r1, r2 try { t1 = arg1.toString().split('.')[1].length } catch (e) {} try { t2 = arg2.toString().split('.')[1].length } catch (e) {} r1 = Number(arg1.toString().replace('.', '')) r2 = Number(arg2.toString().replace('.', '')) return (r1 / r2) * pow(10, t2 - t1) } /** ** 乘法函数,用来得到精确的乘法结果 ** 说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。 ** 调用:accMul(arg1,arg2) ** 返回值:arg1乘以 arg2的精确结果 **/ function accMul(arg1, arg2) { var m = 0, s1 = arg1.toString(), s2 = arg2.toString() try { m += s1.split('.')[1].length } catch (e) {} try { m += s2.split('.')[1].length } catch (e) {} return (Number(s1.replace('.', '')) * Number(s2.replace('.', ''))) / Math.pow(10, m) } /** ** 减法函数,用来得到精确的减法结果 ** 说明:javascript的减法结果会有误差,在两个浮点数相减的时候会比较明显。这个函数返回较为精确的减法结果。 ** 调用:accSub(arg1,arg2) ** 返回值:arg1加上arg2的精确结果 **/ function accSub(arg1, arg2) { var r1, r2, m, n try { r1 = arg1.toString().split('.')[1].length } catch (e) { r1 = 0 } try { r2 = arg2.toString().split('.')[1].length } catch (e) { r2 = 0 } m = Math.pow(10, Math.max(r1, r2)) //last modify by deeka //动态控制精度长度 n = r1 >= r2 ? r1 : r2 return ((arg1 * m - arg2 * m) / m).toFixed(n) } /** ** 加法函数,用来得到精确的加法结果 ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。 ** 调用:accAdd(arg1,arg2) ** 返回值:arg1加上arg2的精确结果 **/ function accAdd(arg1, arg2) { var r1, r2, m, c try { r1 = arg1.toString().split('.')[1].length } catch (e) { r1 = 0 } try { r2 = arg2.toString().split('.')[1].length } catch (e) { r2 = 0 } c = Math.abs(r1 - r2) m = Math.pow(10, Math.max(r1, r2)) if (c > 0) { var cm = Math.pow(10, c) if (r1 > r2) { arg1 = Number(arg1.toString().replace('.', '')) arg2 = Number(arg2.toString().replace('.', '')) * cm } else { arg1 = Number(arg1.toString().replace('.', '')) * cm arg2 = Number(arg2.toString().replace('.', '')) } } else { arg1 = Number(arg1.toString().replace('.', '')) arg2 = Number(arg2.toString().replace('.', '')) } return (arg1 + arg2) / m }