| @ -0,0 +1,229 @@ | |||||
| /** | |||||
| * 天平+PH获取 | |||||
| */ | |||||
| import axios from 'axios' | |||||
| import { Message } from 'element-ui' | |||||
| export async function getBalance( | |||||
| cmd, | |||||
| format, | |||||
| comPort, | |||||
| baudRate, | |||||
| byteSize, | |||||
| parity | |||||
| ) { | |||||
| let val = {} | |||||
| let url = `http://localhost/tpphurl/api/v1/balance/value?cmd=12&format=hex&comPort=COM1&baudRate=9600&byteSize=8&parity=N` | |||||
| // let url = `http://127.0.0.1:${localStorage.getItem('sb_port')}/api/v1/balance/value?cmd=${cmd}&format=${format}&comPort=${comPort}&baudRate=${baudRate}&byteSize=${byteSize}&parity=${parity}` | |||||
| await axios | |||||
| .get( | |||||
| url, | |||||
| {}, | |||||
| { | |||||
| headers: { | |||||
| 'Content-Type': 'application/json' | |||||
| } | |||||
| } | |||||
| ) | |||||
| .then((res) => { | |||||
| if (res.status !== 200) { | |||||
| Message.error('获取天平失败') | |||||
| return | |||||
| } | |||||
| let data = res.data | |||||
| if (data.code !== 200) { | |||||
| Message.error(data.msg || '获取天平数据失败') | |||||
| return | |||||
| } | |||||
| val = parseBalanceData(data.data) | |||||
| debugger | |||||
| }) | |||||
| debugger | |||||
| return await val | |||||
| } | |||||
| export async function getPh(cmd, format, comPort, baudRate, byteSize, parity) { | |||||
| let val = {} | |||||
| let url = `http://localhost/tpphurl/api/v1/ph/value?cmd=12&format=hex&comPort=COM1&baudRate=9600&byteSize=8&parity=N` | |||||
| // let url = `http://127.0.0.1:${localStorage.getItem('sb_port')}/api/v1/ph/value?cmd=${cmd}&format=${format}&comPort=${comPort}&baudRate=${baudRate}&byteSize=${byteSize}&parity=${parity}` | |||||
| await axios | |||||
| .get( | |||||
| url, | |||||
| {}, | |||||
| { | |||||
| headers: { | |||||
| 'Content-Type': 'application/json' | |||||
| } | |||||
| } | |||||
| ) | |||||
| .then((res) => { | |||||
| debugger | |||||
| if (res.status !== 200) { | |||||
| Message.error('获取PH失败') | |||||
| return | |||||
| } | |||||
| let data = res.data | |||||
| if (data.code !== 200) { | |||||
| Message.error(data.msg || '获取PH数据失败') | |||||
| return | |||||
| } | |||||
| val = parseBalanceData(data.data) | |||||
| debugger | |||||
| }) | |||||
| debugger | |||||
| return await val | |||||
| } | |||||
| export function parseBalanceData(rawData, targetUnit = 'g', precision) { | |||||
| // 初始化返回结果,固定字段结构 | |||||
| const result = { | |||||
| success: false, | |||||
| value: '', | |||||
| originalValue: '', | |||||
| originalUnit: '', | |||||
| targetUnit: targetUnit.toLowerCase(), | |||||
| message: '' | |||||
| } | |||||
| // 1. 空值校验:原始数据为空/纯空格,直接返回 | |||||
| if (!rawData || rawData.trim() === '') { | |||||
| result.message = '【解析失败】原始称量数据为空!' | |||||
| return result | |||||
| } | |||||
| const trimedData = rawData.trim() // 预处理:去除首尾空格,避免干扰 | |||||
| // 2. 负数检测:精准匹配「任意空格+负号+任意空格+数字」的场景 | |||||
| const negativeReg = /(\s*)?-(\s*)?\d+/ | |||||
| if (negativeReg.test(rawData)) { | |||||
| result.message = '【解析失败】原始称量数据包含负数,不支持解析!' | |||||
| return result | |||||
| } | |||||
| //2.1 原始数据返回不带计量单位,不支持解析 | |||||
| if (!trimedData.includes('g')) { | |||||
| result.message = '【解析失败】原始数据返回不带计量单位,不支持解析!' | |||||
| } | |||||
| try { | |||||
| // 3. 格式配置化:移除k的匹配,仅保留g/kg | |||||
| const parseFormats = [ | |||||
| { | |||||
| reg: /N\s*(?:[+-]\s*)?(\d+(?:\.\d+)?)\s*([gG]|[kK][gG])/i, | |||||
| desc: 'N + 任意空格 + 可选±号 + 数值 + g/kg' | |||||
| }, | |||||
| { | |||||
| reg: /S\s+S\s*(?:[+-]\s*)?(\d+(?:\.\d+)?)\s*([gG]|[kK][gG])/i, | |||||
| desc: 'S S + 任意空格 + 可选±号 + 数值 + g/kg' | |||||
| }, | |||||
| //添加一种新格式:G 5.00001g | |||||
| { | |||||
| reg: /G\s*(?:[+-]\s*)?(\d+(?:\.\d+)?)\s*([gG]|[kK][gG])/i, | |||||
| desc: 'G + 任意空格 + 可选±号 + 数值 + g/kg' | |||||
| } | |||||
| ] | |||||
| // 4. 遍历格式配置,匹配第一个符合的格式 | |||||
| let matchedFormat = null | |||||
| let matchResult = null | |||||
| for (const format of parseFormats) { | |||||
| matchResult = trimedData.match(format.reg) | |||||
| if (matchResult && matchResult.length >= 3) { | |||||
| matchedFormat = format | |||||
| break | |||||
| } | |||||
| } | |||||
| // 5. 未匹配到任何格式,直接返回 | |||||
| if (!matchedFormat) { | |||||
| result.message = '【解析失败】未匹配到任何预设格式' | |||||
| return result | |||||
| } | |||||
| // 6. 提取匹配结果:数值(分组1)+ 原始单位(分组2) | |||||
| const originalValue = matchResult[1].trim() | |||||
| let originalUnit = matchResult[2].trim().toLowerCase() // 单位转小写统一格式 | |||||
| // 赋值到结果对象 | |||||
| result.originalValue = originalValue | |||||
| result.originalUnit = originalUnit | |||||
| result.message = `【解析成功】匹配到${matchedFormat.desc},提取数值:${originalValue},单位:${originalUnit}` | |||||
| // 7. 数值有效性校验 | |||||
| const num = parseFloat(originalValue) | |||||
| if (isNaN(num)) { | |||||
| result.message = `【换算失败】提取的数值 "${originalValue}" 不是有效数字` | |||||
| return result | |||||
| } | |||||
| // 8. 单位换算核心逻辑 | |||||
| const unitToGram = { g: 1, kg: 1000 } | |||||
| const originalCoeff = unitToGram[result.originalUnit] || 1 | |||||
| const targetCoeff = unitToGram[result.targetUnit] || 1 | |||||
| let convertedValue = (num * originalCoeff) / targetCoeff | |||||
| // 9. 数值格式化:保留原始精度(仅当传入precision时,按指定位数截取,不四舍五入) | |||||
| if (typeof precision === 'number' && precision >= 0) { | |||||
| // 截取指定位数(避免四舍五入) | |||||
| const splitNum = convertedValue.toString().split('.') | |||||
| if (splitNum.length === 1) { | |||||
| convertedValue = splitNum[0] + '.' + '0'.repeat(precision) | |||||
| } else { | |||||
| convertedValue = splitNum[0] + '.' + splitNum[1].slice(0, precision) | |||||
| } | |||||
| result.value = convertedValue | |||||
| } else { | |||||
| // 保留原始精度(不做任何四舍五入和去0) | |||||
| result.value = convertedValue.toString() | |||||
| } | |||||
| // 10. 组装成功结果 | |||||
| result.success = true | |||||
| // 11. 优化提示信息 | |||||
| const baseMsg = result.message.replace('【解析成功】', '【成功】') | |||||
| if (result.originalUnit === result.targetUnit) { | |||||
| result.message = `${baseMsg} → 最终值:${result.value} ${result.targetUnit}` | |||||
| } else { | |||||
| result.message = `${baseMsg} → 换算至${result.targetUnit}:${result.value} ${result.targetUnit}` | |||||
| } | |||||
| } catch (error) { | |||||
| result.message = `【系统错误】解析换算失败:${error.message}` | |||||
| console.error('解析失败堆栈:', error) | |||||
| } | |||||
| return result | |||||
| } | |||||
| export function extractPHValue(rawData) { | |||||
| const result = { | |||||
| success: false, | |||||
| value: '', | |||||
| message: '' | |||||
| } | |||||
| // 空值校验 | |||||
| if (!rawData || rawData.trim() === '') { | |||||
| result.message = '【解析失败】原始数据为空' | |||||
| return result | |||||
| } | |||||
| try { | |||||
| // 正则表达式匹配 pH 值 | |||||
| const phRegex = /^pH\s+(\d+(?:\.\d+)?)\s+pH$/im | |||||
| const match = rawData.match(phRegex) | |||||
| if (match && match.length >= 2) { | |||||
| // 成功提取 pH 值 | |||||
| result.success = true | |||||
| result.value = match[1] // 捕获组中的数值 | |||||
| result.message = `【解析成功】提取到 pH 值:${result.value}` | |||||
| } else { | |||||
| // 未匹配到 pH 值 | |||||
| result.message = '【解析失败】未找到有效的 pH 值' | |||||
| } | |||||
| } catch (error) { | |||||
| result.message = `【系统错误】解析失败:${error.message}` | |||||
| console.error('解析失败堆栈:', error) | |||||
| } | |||||
| return result | |||||
| } | |||||