| @ -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 | |||
| } | |||