one.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. <template>
  2. <view class="container">
  3. <!-- 头部区域 -->
  4. <view class="header">
  5. <u-row>
  6. <u-col span="2">
  7. <view class="status-btn" :class="{ active_btn: communicationLink_1 }">Link</view>
  8. </u-col>
  9. <u-col span="2">
  10. <view class="status-btn" :class="{ active_btn: bleConnected }">blue</view>
  11. </u-col>
  12. <u-col span="6" textAlign="left">
  13. <text class="title">长沙亿旭智能</text>
  14. </u-col>
  15. <u-col span="2">
  16. </u-col>
  17. </u-row>
  18. </view>
  19. <!-- 主要内容区域 -->
  20. <scroll-view class="content" scroll-y>
  21. <view class="param-section">
  22. <!-- 经度 -->
  23. <view class="param-row">
  24. <view class="btn-class">
  25. <u-button type="primary" size="mini" class="param-label">经度</u-button>
  26. </view>
  27. <view class="input-class">
  28. <u-input
  29. @focus="editStatus = true"
  30. @blur="handleBlurWithDelay"
  31. v-model="params.longitude"
  32. placeholder=""
  33. class="param-input"
  34. ></u-input>
  35. </view>
  36. </view>
  37. <!-- 纬度 -->
  38. <view class="param-row">
  39. <view class="btn-class">
  40. <u-button type="primary" size="mini" class="param-label">纬度</u-button>
  41. </view>
  42. <view class="input-class">
  43. <u-input
  44. @focus="editStatus = true"
  45. @blur="handleBlurWithDelay"
  46. v-model="params.latitude"
  47. placeholder=""
  48. class="param-input"
  49. ></u-input>
  50. </view>
  51. </view>
  52. <!-- 时区 -->
  53. <view class="param-row">
  54. <view class="btn-class">
  55. <u-button type="primary" size="mini" class="param-label">时区</u-button>
  56. </view>
  57. <view class="input-class">
  58. <u-input
  59. @focus="editStatus = true"
  60. @blur="handleBlurWithDelay"
  61. v-model="params.timezone"
  62. placeholder=""
  63. class="param-input"
  64. ></u-input>
  65. </view>
  66. <u-radio-group v-model="params.timezoneMode" class="radio-group">
  67. <u-radio label="读" name="read"></u-radio>
  68. <u-radio label="写" name="write"></u-radio>
  69. </u-radio-group>
  70. <u-button :plain="true" :hairline="true" :disabled="params.timezoneMode == 'read'" size="mini" class="action-btn" @click="addValue('READ_TEMPERATURE')">天文写入</u-button>
  71. </view>
  72. <!-- 频点 -->
  73. <view class="param-row">
  74. <view class="btn-class">
  75. <u-button type="warning" size="mini" class="param-label">频点[0-83]</u-button>
  76. </view>
  77. <view class="input-class">
  78. <u-input
  79. @focus="editStatus = true"
  80. @blur="handleBlurWithDelay"
  81. v-model="params.frequency"
  82. placeholder=""
  83. class="param-input"
  84. ></u-input>
  85. </view>
  86. </view>
  87. <!-- 网络ID -->
  88. <view class="param-row">
  89. <view class="btn-class">
  90. <u-button type="warning" size="mini" class="param-label">网络ID</u-button>
  91. </view>
  92. <view class="input-class">
  93. <u-input
  94. @focus="editStatus = true"
  95. @blur="handleBlurWithDelay"
  96. v-model="params.networkId"
  97. placeholder=""
  98. class="param-input"
  99. ></u-input>
  100. </view>
  101. </view>
  102. <!-- 模块地址 -->
  103. <view class="param-row">
  104. <view class="btn-class">
  105. <u-button type="warning" size="mini" class="param-label">模块地址</u-button>
  106. </view>
  107. <view class="input-class">
  108. <u-input
  109. v-model="params.moduleAddress"
  110. placeholder=""
  111. class="param-input"
  112. @focus="editStatus = true"
  113. @blur="handleBlurWithDelay"
  114. ></u-input>
  115. </view>
  116. <u-checkbox-group
  117. placement="column">
  118. <u-checkbox v-model="params.wWl" class="checkbox" label="W_WL" @change="handleWwlChange" >W_WL</u-checkbox>
  119. </u-checkbox-group>
  120. <u-button :plain="true" :hairline="true" :disabled="params.wWl" size="mini" class="action-btn" @click="addValue('WRITE_ADDRESS')">参数写入</u-button>
  121. </view>
  122. <!-- 东限位 -->
  123. <view class="param-row">
  124. <view class="btn-class">
  125. <u-button type="primary" size="mini" class="param-label">东限位(°)</u-button>
  126. </view>
  127. <view class="input-class">
  128. <u-input
  129. v-model="params.eastLimit"
  130. placeholder=""
  131. class="param-input"
  132. @focus="editStatus = true"
  133. @blur="handleBlurWithDelay"
  134. ></u-input>
  135. </view>
  136. </view>
  137. <!-- 西限位 -->
  138. <view class="param-row">
  139. <view class="btn-class">
  140. <u-button type="primary" size="mini" class="param-label">西限位(°)</u-button>
  141. </view>
  142. <view class="input-class">
  143. <u-input
  144. v-model="params.westLimit"
  145. placeholder=""
  146. class="param-input"
  147. @focus="editStatus = true"
  148. @blur="handleBlurWithDelay"
  149. ></u-input>
  150. </view>
  151. <u-checkbox-group
  152. placement="column">
  153. <u-checkbox v-model="params.wLim" class="checkbox" label="W_Lin" @change="limit">W_Lim</u-checkbox>
  154. </u-checkbox-group>
  155. <u-button :plain="true" :hairline="true" :disabled="params.wLim" size="mini" class="action-btn" @click="addValue('READ_LIMIT')">限位写入</u-button>
  156. </view>
  157. <!-- 宽度 -->
  158. <view class="param-row">
  159. <view class="btn-class">
  160. <u-button type="warning" size="mini" class="param-label">宽度</u-button>
  161. </view>
  162. <view class="input-class">
  163. <u-input
  164. v-model="params.width"
  165. placeholder=""
  166. class="param-input"
  167. @focus="editStatus = true"
  168. @blur="handleBlurWithDelay"
  169. ></u-input>
  170. </view>
  171. </view>
  172. <!-- 间距 -->
  173. <view class="param-row">
  174. <view class="btn-class">
  175. <u-button type="warning" size="mini" class="param-label">间距</u-button>
  176. </view>
  177. <view class="input-class">
  178. <u-input
  179. v-model="params.spacing"
  180. placeholder=""
  181. class="param-input"
  182. @focus="editStatus = true"
  183. @blur="handleBlurWithDelay"
  184. ></u-input>
  185. </view>
  186. </view>
  187. <!-- 上坡度 -->
  188. <view class="param-row">
  189. <view class="btn-class">
  190. <u-button type="warning" size="mini" class="param-label">上坡度</u-button>
  191. </view>
  192. <view class="input-class">
  193. <u-input
  194. v-model="params.uphillSlope"
  195. placeholder=""
  196. class="param-input"
  197. @focus="editStatus = true"
  198. @blur="handleBlurWithDelay"
  199. ></u-input>
  200. </view>
  201. </view>
  202. <!-- 下坡度 -->
  203. <view class="param-row">
  204. <view class="btn-class">
  205. <u-button type="warning" size="mini" class="param-label">下坡度</u-button>
  206. </view>
  207. <view class="input-class">
  208. <u-input
  209. v-model="params.downhillSlope"
  210. placeholder=""
  211. class="param-input"
  212. @focus="editStatus = true"
  213. @blur="handleBlurWithDelay"
  214. ></u-input>
  215. </view>
  216. <u-radio-group v-model="params.downhillMode" class="radio-group">
  217. <u-radio label="读" name="read"></u-radio>
  218. <u-radio label="写" name="write"></u-radio>
  219. </u-radio-group>
  220. <u-button :plain="true" :hairline="true" :disabled="params.downhillMode == 'read'" size="mini" class="action-btn" @click="addValue('READ_INCLINATION')">参数写入</u-button>
  221. </view>
  222. </view>
  223. </scroll-view>
  224. <u-modal :show="confirmShow" title="提示" :content='confirmContent' :showCancelButton=true @cancel="cancel" @confirm="confirm" ></u-modal>
  225. </view>
  226. </template>
  227. <script>
  228. import {writeRegister} from '@/utils/modbus.js';
  229. export default {
  230. data() {
  231. return {
  232. editStatus: false,
  233. communicationLink_1: false,
  234. communicationTimer_1: null, // 添加这一行用于保存定时器 ID
  235. selectAction: '',
  236. confirmShow: false,
  237. confirmContent: '是否确定执行该操作?',
  238. checkboxValue1: [],
  239. activeTab: 'home',
  240. params: {
  241. longitude: '',
  242. latitude: '',
  243. latMode: 'read',
  244. timezone: '',
  245. timezoneMode: 'read',
  246. frequency: '',
  247. networkId: '',
  248. moduleAddress: '',
  249. wWl: true,
  250. eastLimit: '',
  251. westLimit: '',
  252. wLim: true,
  253. width: '',
  254. spacing: '',
  255. uphillSlope: '',
  256. uphillMode: 'read',
  257. downhillSlope: '',
  258. downhillMode: 'read'
  259. }
  260. }
  261. },
  262. computed: {
  263. bleConnected() {
  264. return this.$store.getters['ble/connected']
  265. },
  266. bleData() {
  267. return this.$store.getters['ble/data']
  268. }
  269. },
  270. watch: {
  271. bleData: {
  272. handler(newData, oldData) {
  273. if (newData) {
  274. console.log('接收到蓝牙数据:', newData)
  275. // 清除之前的定时器
  276. if (this.communicationTimer_1) {
  277. clearTimeout(this.communicationTimer_1)
  278. this.communicationTimer_1 = null
  279. }
  280. // 设置通信链接状态为 true
  281. this.communicationLink_1 = true
  282. if (!this.editStatus){
  283. this.updateSensorData(newData)
  284. }
  285. }
  286. },
  287. deep: true, // 深度监听,确保嵌套对象变化时也能触发
  288. immediate: true // 立即执行一次
  289. }
  290. },
  291. methods: {
  292. limit(value){
  293. console.log('限制选择:', value)
  294. this.params.wLim = !value;
  295. },
  296. handleWwlChange(value){
  297. this.params.wWl = !value;
  298. },
  299. handleBlurWithDelay() {
  300. setTimeout(() => {
  301. this.editStatus = false;
  302. }, 1000);
  303. },
  304. cancel(){
  305. this.confirmShow = false
  306. },
  307. addValue(action) {
  308. this.selectAction = action;
  309. this.confirmShow = true;
  310. },
  311. confirm() {
  312. const action = this.selectAction;
  313. switch (action) {
  314. case 'READ_TEMPERATURE': // 天文写入
  315. const longitude = parseFloat(this.params.longitude || "0");
  316. const latitude = parseFloat(this.params.latitude || "0");
  317. const timezone = parseFloat(this.params.timezone || "0");
  318. // 转换为带两位小数的整数(乘以100)
  319. const intValue1 = Math.round(longitude * 100);
  320. const intValue2 = Math.round(latitude * 100);
  321. const intValue3 = Math.round(timezone * 100);
  322. // 创建数组存储值
  323. const values = [];
  324. values.push(intValue1);
  325. values.push(intValue2);
  326. values.push(intValue3);
  327. writeRegister("READ_TEMPERATURE",values);
  328. break
  329. case 'WRITE_ADDRESS': // 网络地址写入
  330. // 获取输入值
  331. let frequency = parseInt(this.params.frequency) || 0; // 频点
  332. let networkId = parseInt(this.params.networkId) || 0; // 网络ID
  333. let moduleAddr = parseInt(this.params.moduleAddress) || 0; // 模块地址
  334. // 限制频点范围为0-83
  335. frequency = Math.max(0, Math.min(83, frequency));
  336. // 计算模块地址: 网络ID * 256 + 设备地址
  337. let calculatedModuleAddr = (networkId * 256) + moduleAddr;
  338. // 创建值数组
  339. let addressValues = [frequency, networkId, calculatedModuleAddr];
  340. // 调用写入寄存器函数
  341. writeRegister("READ_FREQUENCY", addressValues);
  342. break
  343. case 'READ_LIMIT': // 限位写入
  344. let eastLimit = parseInt(this.params.eastLimit) || 0;
  345. let westLimit = parseInt(this.params.westLimit) || 0;
  346. let limit = [eastLimit, westLimit];
  347. writeRegister("READ_LIMIT",limit);
  348. break
  349. case 'READ_INCLINATION': // 坡度写入
  350. let width = parseFloat( this.params.width);
  351. let interval = parseFloat(this.params.spacing);
  352. let upgrade = parseFloat(this.params.uphillSlope);
  353. let downgrade = parseFloat(this.params.downhillSlope);
  354. // 转换为16位整数并乘以100
  355. let number = Math.floor(width * 100);
  356. let number1 = Math.floor(interval * 100);
  357. let number2 = Math.floor(upgrade * 100);
  358. let number3 = Math.floor(downgrade * 100);
  359. let number4 = [number, number1, number2, number3];
  360. writeRegister("READ_INCLINATION",number4);
  361. break
  362. }
  363. this.confirmShow = false;
  364. uni.showToast({
  365. title: '操作执行成功!',
  366. icon: 'success',
  367. duration: 2000
  368. });
  369. },
  370. handleLink() {
  371. uni.showToast({
  372. title: '连接设备',
  373. icon: 'none'
  374. })
  375. },
  376. switchTab(tab) {
  377. this.activeTab = tab
  378. uni.showToast({
  379. title: `切换到${tab}`,
  380. icon: 'none'
  381. })
  382. },
  383. updateSensorData(data) {
  384. // 根据蓝牙数据更新参数值
  385. if (data.Longitude_50 !== undefined && this.params.timezoneMode == 'read') {
  386. this.params.longitude = data.Longitude_50
  387. }
  388. if (data.Latitude_51 !== undefined && this.params.timezoneMode == 'read') {
  389. this.params.latitude = data.Latitude_51
  390. }
  391. if (data.TimeZone_52 !== undefined && this.params.timezoneMode == 'read') {
  392. this.params.timezone = data.TimeZone_52
  393. }
  394. if (data.Frequence_25 !== undefined && this.params.wWl) {
  395. this.params.frequency = data.Frequence_25
  396. }
  397. if (data.NetworkId_26 !== undefined && this.params.wWl) {
  398. this.params.networkId = data.NetworkId_26
  399. }
  400. if (data.modAddre_27 !== undefined && this.params.wWl) {
  401. this.params.moduleAddress = data.modAddre_27
  402. }
  403. if (data.qEasternLimit_64 !== undefined && this.params.wLim) {
  404. this.params.eastLimit = data.qEasternLimit_64
  405. }
  406. if (data.qWesternLimit_65 !== undefined && this.params.wLim) {
  407. this.params.westLimit = data.qWesternLimit_65
  408. }
  409. if (data.qwidth_60 !== undefined && this.params.downhillMode == 'read') {
  410. this.params.width = data.qwidth_60
  411. }
  412. if (data.Interval_61 !== undefined && this.params.downhillMode == 'read') {
  413. this.params.spacing = data.Interval_61
  414. }
  415. if (data.UpGrade_62 !== undefined && this.params.downhillMode == 'read') {
  416. this.params.uphillSlope = data.UpGrade_62
  417. }
  418. if (data.DownGrade_63 !== undefined && this.params.downhillMode == 'read') {
  419. this.params.downhillSlope = data.DownGrade_63
  420. }
  421. // 设置6秒后将 communicationLink_1 设置为 false 的定时器
  422. this.communicationTimer_1 = setTimeout(() => {
  423. this.communicationLink_1 = false
  424. this.communicationTimer_1 = null
  425. }, 5000)
  426. }
  427. }
  428. }
  429. </script>
  430. <style lang="scss" >
  431. @import '@/static/scss/custom-theme.scss';
  432. .container {
  433. height: calc(100vh - 140px);
  434. display: flex;
  435. flex-direction: column;
  436. background-color: $custom-bg-tertiary;
  437. }
  438. .status-bar {
  439. height: $custom-status-height;
  440. background-color: $custom-bg-primary;
  441. @include flex-between;
  442. padding: 0 $custom-spacing-md;
  443. font-size: 14px;
  444. .status-left {
  445. color: $custom-text-primary;
  446. }
  447. .status-right {
  448. @include flex-start;
  449. gap: $custom-spacing-xs;
  450. .data-rate {
  451. color: $custom-text-secondary;
  452. font-size: 12px;
  453. }
  454. .wifi-icon, .hd-text, .network, .battery {
  455. font-size: 12px;
  456. }
  457. }
  458. }
  459. .header {
  460. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  461. padding: 20rpx;
  462. .link-btn {
  463. background-color: #ff4757;
  464. border: none;
  465. width: 60px;
  466. margin-left: 0px;
  467. }
  468. .title {
  469. color: #fff;
  470. font-size: 36rpx;
  471. font-weight: bold;
  472. }
  473. .status-btn {
  474. background-color: #ff4757;
  475. border: none;
  476. margin-left: 0px;
  477. padding: 0px;
  478. width: 40px;
  479. text-align: center;
  480. color: white;
  481. border-radius: 4px;
  482. height: 20px;
  483. line-height: 20px;
  484. }
  485. .active_btn {
  486. background-color: yellowgreen !important;
  487. }
  488. }
  489. .content {
  490. flex: 1;
  491. padding: $custom-spacing-md;
  492. height: calc(100vh - 60px);
  493. }
  494. .param-section {
  495. @include card-style;
  496. overflow: auto;
  497. }
  498. .param-row {
  499. @include flex-start;
  500. margin-bottom: $custom-spacing-md;
  501. gap: $custom-spacing-sm;
  502. height: 40px;
  503. .param-label {
  504. width: 70px;
  505. @include button-style('primary');
  506. }
  507. .param-input {
  508. flex: 1;
  509. width: 60px;
  510. @include input-style;
  511. }
  512. .radio-group {
  513. @include flex-start;
  514. gap: $custom-spacing-md;
  515. }
  516. .checkbox {
  517. margin-left: $custom-spacing-sm;
  518. }
  519. .action-btn {
  520. border: 1px solid $custom-border-secondary;
  521. height: 20px;
  522. line-height: 20px;
  523. margin-right: 0px;
  524. }
  525. }
  526. // 响应式设计
  527. @include responsive(md) {
  528. .param-row {
  529. .param-input {
  530. min-width: 150px;
  531. }
  532. }
  533. }
  534. @include responsive(lg) {
  535. .param-row {
  536. .param-input {
  537. min-width: 200px;
  538. }
  539. }
  540. }
  541. ::v-deep .param-section .u-button--mini{
  542. width: 80px !important;
  543. height: 36px !important;
  544. font-size: 10px !important;
  545. }
  546. ::v-deep .param-section .u-input{
  547. width: 60px !important;
  548. }
  549. ::v-deep .content text{
  550. font-size: 12px !important;
  551. }
  552. </style>