From 0afa485528fb400e2a8922e23b8b982247edca52 Mon Sep 17 00:00:00 2001 From: memorylkf <312904636@qq.com> Date: Wed, 8 Apr 2026 14:24:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20[=E4=BB=AA=E5=99=A8=E5=AF=B9=E6=8E=A5]?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E8=8E=B7=E5=8F=96=E5=A4=A9=E5=B9=B3+PH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/tpph.js | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/login.vue | 12 +++ vue.config.js | 9 ++- 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/utils/tpph.js diff --git a/src/utils/tpph.js b/src/utils/tpph.js new file mode 100644 index 0000000..96718a6 --- /dev/null +++ b/src/utils/tpph.js @@ -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 +} diff --git a/src/views/login.vue b/src/views/login.vue index 04bcc73..36fc391 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -77,6 +77,8 @@ import Cookies from "js-cookie"; import { encrypt, decrypt } from '@/utils/jsencrypt' import defaultSettings from '@/settings' +import { getBalance,getPh } from "@/utils/tpph"; + export default { name: "Login", components: { LangSelect }, @@ -119,6 +121,10 @@ export default { } }, created() { + let port = this.$route.query.port + if(port){ + localStorage.setItem(`sb_port`, port); + } this.getCode(); // this.getCookie(); }, @@ -143,6 +149,12 @@ export default { force:false }; }, + async testGetTpph() { + let x = await getBalance() + debugger + let y = await getPh() + debugger + }, handleLogin() { this.$refs.loginForm.validate(valid => { if (valid) { diff --git a/vue.config.js b/vue.config.js index bf3ddf1..b154aa0 100644 --- a/vue.config.js +++ b/vue.config.js @@ -35,11 +35,18 @@ module.exports = { // detail: https://cli.vuejs.org/config/#devserver-proxy [process.env.VUE_APP_BASE_API]: { // target: `http://localhost:8080`, - target: `http://39.99.251.173:8080`, + target: `http://39.99.251.173:8080`, changeOrigin: true, pathRewrite: { ['^' + process.env.VUE_APP_BASE_API]: '' } + }, + '/tpphurl': { + target: 'http://192.168.0.68:9600', + changeOrigin: true, + pathRewrite: { + '^/tpphurl': '' // 确保路径重写正确 + } } }, disableHostCheck: true