one.vue 16 KB

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