tunnel.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. <template>
  2. <el-container>
  3. <el-header class="gva-search-box">
  4. <el-form
  5. v-model="searchData"
  6. :inline="true"
  7. style="line-height: 75px"
  8. >
  9. <el-form-item label="名称">
  10. <el-input
  11. v-model="searchData.name"
  12. />
  13. </el-form-item>
  14. <el-form-item label="类型">
  15. <el-select
  16. v-model.number="searchData.regionId"
  17. style="width: 240px"
  18. clearable
  19. >
  20. <el-option
  21. v-for="item in region"
  22. :key="item.ID"
  23. :label="item.name"
  24. :value="item.ID"
  25. />
  26. </el-select>
  27. </el-form-item>
  28. <el-form-item>
  29. <el-button
  30. type="primary"
  31. @click="getData"
  32. >查询</el-button>
  33. </el-form-item>
  34. </el-form>
  35. </el-header>
  36. <el-main class="gva-table-box">
  37. <div style="margin: 0 0 20px 0 ">
  38. <el-button
  39. type="success"
  40. @click="isTunnelAdd"
  41. >添加</el-button>
  42. <el-button
  43. type="primary"
  44. :disabled="tunnelIds.length === 0"
  45. @click="allocationRegionDialog = true"
  46. >分配</el-button>
  47. </div>
  48. <el-table
  49. :data="tunnel"
  50. style="width: 100%;min-height:600px"
  51. row-key="id"
  52. @selection-change="handleSelectionChange"
  53. >
  54. <el-table-column
  55. type="selection"
  56. width="55"
  57. align="center"
  58. />
  59. <el-table-column
  60. prop="tunnelSn"
  61. label="序号"
  62. align="center"
  63. />
  64. <el-table-column
  65. prop="name"
  66. label="名称"
  67. align="center"
  68. />
  69. <el-table-column
  70. prop="region.name"
  71. label="地区"
  72. align="center"
  73. />
  74. <el-table-column
  75. prop="switchType"
  76. label="开关类型"
  77. align="center"
  78. />
  79. <el-table-column
  80. label="策略"
  81. align="center"
  82. >
  83. <template #default="scope">
  84. <el-select
  85. v-model="scope.row.tactics"
  86. style="width: 100px"
  87. @change="changeTactics(scope.row)"
  88. >
  89. <el-option
  90. v-for="item in tacticsOptions"
  91. :key="item.value"
  92. :label="item.label"
  93. :value="item.value"
  94. />
  95. </el-select>
  96. </template>
  97. </el-table-column>
  98. <el-table-column
  99. label="操作"
  100. align="center"
  101. width="500"
  102. >
  103. <template #default="scope">
  104. <el-button
  105. type="primary"
  106. size="small"
  107. @click="jumpScreen(scope.row)"
  108. >
  109. 大屏
  110. </el-button>
  111. <el-button
  112. type="primary"
  113. size="small"
  114. @click="tunnelData = scope.row ; tunnelEditDialog = true"
  115. >
  116. 修改
  117. </el-button>
  118. <el-button
  119. type="danger"
  120. size="small"
  121. @click="tunnelDelete(scope.row)"
  122. >
  123. 删除
  124. </el-button>
  125. <el-button
  126. type="primary"
  127. size="small"
  128. @click="tunnelControlPanel(scope.row)"
  129. >
  130. 控制面板
  131. </el-button>
  132. <el-button
  133. type="success"
  134. size="small"
  135. @click="tunnelDataPanel(scope.row)"
  136. >
  137. 数据面板
  138. </el-button>
  139. <el-button
  140. type="primary"
  141. size="small"
  142. @click="getDeviceFile(scope.row.ID)"
  143. >
  144. 生成设备文件
  145. </el-button>
  146. </template>
  147. </el-table-column>
  148. </el-table>
  149. <div class="gva-pagination">
  150. <el-pagination
  151. :current-page="searchData.pageInfo.page"
  152. :page-size="searchData.pageInfo.pageSize"
  153. :page-sizes="[10, 30, 50, 100]"
  154. :total="total"
  155. layout="total, sizes, prev, pager, next, jumper"
  156. @current-change="handleCurrentChange"
  157. @size-change="handleSizeChange"
  158. />
  159. </div>
  160. </el-main>
  161. <!-- 隧道添加-->
  162. <el-dialog
  163. v-model="tunnelAddDialog"
  164. title="隧道添加"
  165. width="500"
  166. align-center
  167. >
  168. <el-form
  169. v-model="tunnelData"
  170. style="line-height: 75px"
  171. >
  172. <el-form-item label="名称">
  173. <el-input
  174. v-model="tunnelData.name"
  175. style="width: 200px;"
  176. />
  177. </el-form-item>
  178. <el-form-item label="序号">
  179. <el-input
  180. v-model="tunnelData.tunnelSn"
  181. style="width: 200px;"
  182. />
  183. </el-form-item>
  184. <el-form-item label="地区">
  185. <el-select
  186. v-model.number="tunnelData.regionId"
  187. style="width: 240px"
  188. clearable
  189. >
  190. <el-option
  191. v-for="item in region"
  192. :key="item.ID"
  193. :label="item.name"
  194. :value="item.ID"
  195. />
  196. </el-select>
  197. </el-form-item>
  198. <el-form-item
  199. v-if="userInfo.authorityId === 888"
  200. label="开关类型"
  201. >
  202. <el-input
  203. v-model="tunnelData.switchType"
  204. style="width: 200px;"
  205. />
  206. </el-form-item>
  207. </el-form>
  208. <template #footer>
  209. <div class="dialog-footer">
  210. <el-button @click="tunnelAddDialog = false">取消</el-button>
  211. <el-button
  212. type="primary"
  213. @click="tunnelAdd"
  214. >
  215. 确定
  216. </el-button>
  217. </div>
  218. </template>
  219. </el-dialog>
  220. <!-- 隧道修改-->
  221. <el-dialog
  222. v-model="tunnelEditDialog"
  223. title="隧道修改"
  224. width="500"
  225. align-center
  226. >
  227. <el-form
  228. v-model="tunnelData"
  229. style="line-height: 75px"
  230. >
  231. <el-form-item label="名称">
  232. <el-input
  233. v-model="tunnelData.name"
  234. style="width: 200px;"
  235. />
  236. </el-form-item>
  237. <el-form-item label="序号">
  238. <el-input
  239. v-model="tunnelData.tunnelSn"
  240. style="width: 200px;"
  241. />
  242. </el-form-item>
  243. <el-form-item label="地区">
  244. <el-select
  245. v-model.number="tunnelData.regionId"
  246. style="width: 240px"
  247. clearable
  248. >
  249. <el-option
  250. v-for="item in region"
  251. :key="item.ID"
  252. :label="item.name"
  253. :value="item.ID"
  254. />
  255. </el-select>
  256. </el-form-item>
  257. <el-form-item
  258. v-if="userInfo.authorityId === 888"
  259. label="开关类型"
  260. >
  261. <el-input
  262. v-model="tunnelData.switchType"
  263. style="width: 200px;"
  264. />
  265. </el-form-item>
  266. </el-form>
  267. <template #footer>
  268. <div class="dialog-footer">
  269. <el-button @click="tunnelEditDialog = false">取消</el-button>
  270. <el-button
  271. type="primary"
  272. @click="tunnelEdit"
  273. >
  274. 确定
  275. </el-button>
  276. </div>
  277. </template>
  278. </el-dialog>
  279. <!-- 隧道分配-->
  280. <el-dialog
  281. v-model="allocationRegionDialog"
  282. title="隧道分配"
  283. width="500"
  284. align-center
  285. >
  286. <el-form>
  287. <el-form-item label="地区">
  288. <el-select
  289. v-model.number="regionId"
  290. style="width: 240px"
  291. clearable
  292. >
  293. <el-option
  294. v-for="item in region"
  295. :key="item.ID"
  296. :label="item.name"
  297. :value="item.ID"
  298. />
  299. </el-select>
  300. </el-form-item>
  301. </el-form>
  302. <template #footer>
  303. <div class="dialog-footer">
  304. <el-button @click="allocationRegionDialog = false">取消</el-button>
  305. <el-button
  306. type="primary"
  307. @click="allocationRegion"
  308. >
  309. 确定
  310. </el-button>
  311. </div>
  312. </template>
  313. </el-dialog>
  314. <!-- 生成设备文件-->
  315. <el-drawer
  316. v-model="isDeviceFile"
  317. title="设备"
  318. direction="rtl"
  319. size="80%"
  320. >
  321. <el-button @click="downloadDeviceFile">下载</el-button>
  322. </el-drawer>
  323. <!-- 控制面板-->
  324. <el-drawer
  325. v-model="isControlPanel"
  326. title="控制面板"
  327. direction="rtl"
  328. size="80%"
  329. >
  330. <el-collapse
  331. v-model="activeNames"
  332. >
  333. <el-collapse-item
  334. title="开关"
  335. name="1"
  336. >
  337. <div v-if="tunnelTimeData.switchType === '四路控制器'">
  338. <div
  339. v-for="(item, index) in tunnelTimeData.devices"
  340. key="index"
  341. style="margin: 10px 0"
  342. >
  343. <div v-if="item.genre === 6">
  344. <span style="margin: 0 20px 0 0;font-weight: 600;font-size: 16px">道路 {{ item.radarId }}</span>
  345. <el-switch
  346. v-for="(v, k) in item.deviceRelays"
  347. key="k"
  348. v-model="v.state"
  349. class="ml-2"
  350. :disabled="k === 0"
  351. style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
  352. @click="switchButton(item, v, k)"
  353. />
  354. </div>
  355. </div>
  356. </div>
  357. <div v-if="tunnelTimeData.switchType === '单灯控制器'">
  358. <div style="margin: 0 0 0 20px">
  359. <el-slider
  360. v-model="tunnelTimeData.lampValue1"
  361. :step="50"
  362. style="width: 50%;"
  363. show-stops
  364. />
  365. </div>
  366. <div style="margin: 0 0 0 20px">
  367. <el-slider
  368. v-model="tunnelTimeData.lampValue2"
  369. :step="50"
  370. style="width: 50%;"
  371. show-stops
  372. />
  373. </div>
  374. <el-button
  375. type="success"
  376. @click="lampSet(tunnelTimeData)"
  377. >设定</el-button>
  378. </div>
  379. </el-collapse-item>
  380. <el-collapse-item
  381. title="定时"
  382. name="2"
  383. >
  384. <div style="margin-bottom: 30px">
  385. <span style="margin-right: 30px">开始:</span>
  386. <el-time-select
  387. v-model="tunnelTiming.startTime"
  388. style="width: 150px"
  389. start="00:00"
  390. end="23:55"
  391. step="00:05"
  392. format="HH:mm"
  393. />
  394. </div>
  395. <div style="margin-bottom: 30px">
  396. <span style="margin-right: 30px">结束:</span>
  397. <el-time-select
  398. v-model="tunnelTiming.endTime"
  399. style="width: 150px"
  400. start="00:00"
  401. end="23:55"
  402. step="00:05"
  403. format="HH:mm"
  404. />
  405. </div>
  406. <div>
  407. <el-button
  408. type="success"
  409. @click="editTunnelTiming"
  410. >
  411. 存储数据
  412. </el-button>
  413. <!-- <span style="margin-left: 30px">-->
  414. <!-- &lt;!&ndash; <el-tag&ndash;&gt;-->
  415. <!-- &lt;!&ndash; v-if="tunnelTimeData.tunnelTime.isComplete"&ndash;&gt;-->
  416. <!-- &lt;!&ndash; type="success"&ndash;&gt;-->
  417. <!-- &lt;!&ndash; >完成</el-tag>&ndash;&gt;-->
  418. <!-- <el-tag-->
  419. <!-- v-if="!tunnelTimeData.tunnelTime.isComplete"-->
  420. <!-- type="warning"-->
  421. <!-- >正在发送</el-tag>-->
  422. <!-- </span>-->
  423. </div>
  424. </el-collapse-item>
  425. </el-collapse>
  426. </el-drawer>
  427. <!-- 数据面板-->
  428. <el-drawer
  429. v-model="isDataPanel"
  430. title="数据面板"
  431. direction="rtl"
  432. size="80%"
  433. >
  434. <el-collapse
  435. v-model="dataNames"
  436. >
  437. <el-collapse-item
  438. title="环境"
  439. name="1"
  440. >
  441. <div
  442. v-for="[sn, data] in Array.from(groupedBySn)"
  443. :id="'chart-' + sn"
  444. :key="sn"
  445. style="width: 600px; height: 400px; margin: 10px;"
  446. />
  447. </el-collapse-item>
  448. <el-collapse-item
  449. title="光感"
  450. name="2"
  451. >
  452. <div
  453. v-for="[sn, data] in Array.from(lightBySn)"
  454. :id="'chart-' + sn"
  455. :key="sn"
  456. style="width: 600px; height: 400px; margin: 10px;"
  457. />
  458. </el-collapse-item>
  459. </el-collapse>
  460. </el-drawer>
  461. </el-container>
  462. </template>
  463. <script setup>
  464. import { ref, onMounted } from 'vue'
  465. import { useScreenStore } from '@/pinia/modules/screen'
  466. import { queryAllRegions } from '@/api/region'
  467. import {
  468. createTunnel,
  469. deleteTunnel,
  470. queryTunnelList, updateTactics,
  471. updateTunnel, updateTunnelLamp,
  472. updateTunnelsRegion,
  473. updateTunnelTime
  474. } from '@/api/tunnel'
  475. import { ElMessage, ElMessageBox } from 'element-plus'
  476. import { nextTick } from 'vue'
  477. import { deviceSwitch, generateDeviceFile } from '@/api/device'
  478. import * as echarts from 'echarts'
  479. import { useUserStore } from '@/pinia/modules/user'
  480. const userData = useUserStore()
  481. const userInfo = userData.userInfo
  482. import { useRouter } from 'vue-router'
  483. const router = useRouter()
  484. const lampList = [33, 66, 100]
  485. const searchData = ref({
  486. pageInfo: {
  487. page: 1,
  488. pageSize: 10
  489. },
  490. name: '',
  491. regionId: undefined,
  492. userId: userInfo.ID
  493. })
  494. // 分页
  495. const handleSizeChange = (val) => {
  496. searchData.value.pageInfo.pageSize = val
  497. getData()
  498. }
  499. const handleCurrentChange = (val) => {
  500. searchData.value.pageInfo.page = val
  501. getData()
  502. }
  503. const total = ref(0)
  504. const region = ref()
  505. const tunnel = ref()
  506. const getData = async() => {
  507. await queryAllRegions().then(res => {
  508. region.value = res.data
  509. })
  510. await queryTunnelList(searchData.value).then(res => {
  511. console.log(res.data.list)
  512. tunnel.value = res.data.list
  513. total.value = res.data.total
  514. searchData.value.pageInfo.page = res.data.page
  515. searchData.value.pageInfo.pageSize = res.data.pageSize
  516. })
  517. }
  518. // 新增
  519. const tunnelAddDialog = ref(false)
  520. const isTunnelAdd = () => {
  521. tunnelAddDialog.value = true
  522. tunnelData.value.tunnelSn = 'LC' + getFormattedDateTime()
  523. }
  524. function getFormattedDateTime() {
  525. const now = new Date()
  526. const year = now.getFullYear()
  527. const month = String(now.getMonth() + 1).padStart(2, '0') // 月份从0开始,所以需要加1
  528. const day = String(now.getDate()).padStart(2, '0')
  529. const hour = String(now.getHours()).padStart(2, '0')
  530. const minute = String(now.getMinutes()).padStart(2, '0')
  531. const second = String(now.getSeconds()).padStart(2, '0')
  532. return `${year}${month}${day}${hour}${minute}${second}`
  533. }
  534. const tunnelData = ref({
  535. id: 0,
  536. name: '',
  537. regionId: undefined,
  538. tunnelSn: '',
  539. switchType: ''
  540. })
  541. const tunnelAdd = async() => {
  542. tunnelData.value.id = 0
  543. await createTunnel(tunnelData.value).then(res => {
  544. if (res.code === 0) {
  545. ElMessage.success('添加成功')
  546. }
  547. tunnelAddDialog.value = false
  548. getData()
  549. })
  550. }
  551. // 修改
  552. const tunnelEditDialog = ref(false)
  553. const tunnelEdit = async() => {
  554. await updateTunnel(tunnelData.value).then(res => {
  555. if (res.code === 0) {
  556. ElMessage.success('修改成功')
  557. }
  558. tunnelEditDialog.value = false
  559. getData()
  560. })
  561. }
  562. // 删除
  563. const tunnelDelete = (val) => {
  564. ElMessageBox.confirm(
  565. '将永久删除改数据,请问继续吗?',
  566. '删除',
  567. {
  568. confirmButtonText: '确定',
  569. cancelButtonText: '取消',
  570. type: 'warning',
  571. }
  572. )
  573. .then(async() => {
  574. await deleteTunnel(val.ID).then(res => {
  575. if (res.code === 0) {
  576. ElMessage.success('删除成功')
  577. }
  578. getData()
  579. })
  580. })
  581. .catch(() => {
  582. ElMessage({
  583. type: 'info',
  584. message: '删除已取消',
  585. })
  586. })
  587. }
  588. // 多选
  589. const tunnelIds = ref([])
  590. const handleSelectionChange = (val) => {
  591. const array = []
  592. for (const i in val) {
  593. array.push(val[i].ID)
  594. }
  595. tunnelIds.value = array
  596. }
  597. // 分配
  598. const allocationRegionDialog = ref(false)
  599. const regionId = ref()
  600. const allocationRegion = async() => {
  601. await updateTunnelsRegion({
  602. tunnelIds: tunnelIds.value,
  603. regionId: regionId.value
  604. }).then(res => {
  605. if (res.code === 0) {
  606. ElMessage.success('分配成功')
  607. tunnelIds.value = []
  608. getData()
  609. }
  610. allocationRegionDialog.value = false
  611. })
  612. }
  613. // 生成设备文件
  614. const isDeviceFile = ref(false)
  615. const fileData = ref()
  616. const getDeviceFile = async(val) => {
  617. isDeviceFile.value = true
  618. await generateDeviceFile(val).then(res => {
  619. fileData.value = res.data
  620. })
  621. }
  622. const downloadDeviceFile = () => {
  623. // 将对象转换为 JSON 字符串
  624. const jsonString = JSON.stringify(fileData.value, null, 2)
  625. // 创建一个新的 Blob 对象
  626. const blob = new Blob([jsonString], { type: 'application/json' })
  627. // 创建一个隐藏的可下载链接
  628. const url = window.URL.createObjectURL(blob)
  629. const link = document.createElement('a')
  630. // 设置链接的 href 和 download 属性
  631. link.href = url
  632. link.setAttribute('download', 'data.json') // 下载文件名
  633. // 将链接添加到 DOM 中
  634. document.body.appendChild(link)
  635. // 触发点击事件,开始下载
  636. link.click()
  637. // 下载完成后移除链接并释放 URL 对象
  638. link.remove()
  639. window.URL.revokeObjectURL(url) // 清理资源
  640. }
  641. // 策略
  642. const tacticsOptions = [
  643. {
  644. value: 1,
  645. label: '环境',
  646. },
  647. {
  648. value: 2,
  649. label: '雷达',
  650. },
  651. {
  652. value: 3,
  653. label: '定时',
  654. }
  655. ]
  656. const changeTactics = (val) => {
  657. ElMessageBox.confirm(
  658. '你确定修改当前策略吗?',
  659. '警告',
  660. {
  661. confirmButtonText: '确定',
  662. cancelButtonText: '取消',
  663. type: 'warning',
  664. }
  665. )
  666. .then(async() => {
  667. await updateTactics({
  668. sn: val.tunnelSn,
  669. tactics: val.tactics
  670. }).then(res => {
  671. if (res.code === 0) {
  672. ElMessage.success('修改成功')
  673. }
  674. getData()
  675. })
  676. })
  677. .catch(() => {
  678. ElMessage({
  679. type: 'info',
  680. message: '取消修改',
  681. })
  682. })
  683. }
  684. // 控制面板
  685. const tunnelTimeData = ref()
  686. const isControlPanel = ref(false)
  687. const tunnelControlPanel = (val) => {
  688. console.log(val)
  689. isControlPanel.value = true
  690. const lampObj = {
  691. 0: 0,
  692. 33: 0,
  693. 50: 50,
  694. 66: 50,
  695. 100: 100,
  696. }
  697. val.lampValue1 = lampObj[val.lampValue1]
  698. val.lampValue2 = lampObj[val.lampValue2]
  699. tunnelTimeData.value = val
  700. tunnelTiming.value = val.tunnelTime
  701. }
  702. const activeNames = ref(['1', '2'])
  703. // 定时
  704. const tunnelTiming = ref({
  705. startTime: '00:00',
  706. endTime: '00:00'
  707. })
  708. const editTunnelTiming = async() => {
  709. console.log(tunnelTiming.value)
  710. await updateTunnelTime(tunnelTiming.value).then(res => {
  711. if (res.code === 0) {
  712. ElMessage.success('已发送')
  713. }
  714. getData()
  715. })
  716. }
  717. const lampSet = async(val) => {
  718. const judge = {
  719. 0: 33,
  720. 50: 66,
  721. 100: 100
  722. }
  723. await updateTunnelLamp({
  724. id: val.ID,
  725. tunnelSn: val.tunnelSn,
  726. lampValue1: judge[val.lampValue1],
  727. lampValue2: judge[val.lampValue2]
  728. }).then(res => {
  729. if (res.code === 0) {
  730. ElMessage.success('已发送')
  731. }
  732. getData()
  733. })
  734. }
  735. // 数据面板
  736. const isDataPanel = ref(false)
  737. const dataNames = ref(['1'])
  738. const groupedBySn = ref()
  739. const lightBySn = ref()
  740. const tunnelDataPanel = (val) => {
  741. isDataPanel.value = true
  742. tunnelTimeData.value = val
  743. console.log('数据面板',val)
  744. groupedBySn.value = tunnelTimeData.value.envData.reduce((acc, current) => {
  745. const { sn } = current
  746. // 如果 acc(累加器)中没有当前 sn 对应的数组,则创建一个新的数组
  747. if (!acc.has(sn)) {
  748. acc.set(sn, [])
  749. }
  750. // 将当前对象添加到对应 sn 的数组中
  751. acc.get(sn).push(current)
  752. return acc
  753. }, new Map())
  754. lightBySn.value = tunnelTimeData.value.opticalData.reduce((acc, current) => {
  755. const { sn } = current
  756. // 如果 acc(累加器)中没有当前 sn 对应的数组,则创建一个新的数组
  757. if (!acc.has(sn)) {
  758. acc.set(sn, [])
  759. }
  760. // 将当前对象添加到对应 sn 的数组中
  761. acc.get(sn).push(current)
  762. return acc
  763. }, new Map())
  764. nextTick(() => {
  765. groupedBySn.value.forEach((data, index) => {
  766. initChart(index, data)
  767. })
  768. lightBySn.value.forEach((data, index) => {
  769. initLightBySnChart(index, data)
  770. })
  771. })
  772. }
  773. // 环境
  774. function initChart(index, data) {
  775. const chartDom = document.getElementById('chart-' + index)
  776. if (!chartDom) {
  777. console.error(`无法找到元素: chart-${index}`)
  778. return
  779. }
  780. const myChart = echarts.init(chartDom)
  781. const option = {
  782. title: {
  783. text: '环境监测'
  784. },
  785. tooltip: {
  786. trigger: 'axis'
  787. },
  788. legend: {
  789. data: ['温度', '湿度', '光照度']
  790. },
  791. xAxis: {
  792. type: 'time', // 使用时间类型的x轴
  793. boundaryGap: false,
  794. },
  795. yAxis: {},
  796. series: [
  797. {
  798. name: '温度',
  799. type: 'line',
  800. data: data.map(item => [new Date(item.CreatedAt).getTime(), item.temperature])
  801. },
  802. {
  803. name: '湿度',
  804. type: 'line',
  805. data: data.map(item => [new Date(item.CreatedAt).getTime(), item.humidity])
  806. },
  807. {
  808. name: '光照度',
  809. type: 'line',
  810. data: data.map(item => [new Date(item.CreatedAt).getTime(), item.illuminance])
  811. }
  812. ],
  813. dataZoom: [
  814. {
  815. type: 'slider', // 滑动条型数据区域缩放组件
  816. start: 0, // 默认显示数据的起始百分比
  817. end: 100 // 默认显示数据的结束百分比
  818. },
  819. {
  820. type: 'inside', // 支持鼠标滚轮和双指缩放
  821. start: 0,
  822. end: 100
  823. }
  824. ]
  825. }
  826. myChart.setOption(option)
  827. }
  828. // 光感
  829. function initLightBySnChart(index, data) {
  830. const chartDom = document.getElementById('chart-' + index)
  831. if (!chartDom) {
  832. console.error(`无法找到元素: chart-${index}`)
  833. return
  834. }
  835. const myChart = echarts.init(chartDom)
  836. const option = {
  837. title: {
  838. text: '光感监测'
  839. },
  840. tooltip: {
  841. trigger: 'axis'
  842. },
  843. legend: {
  844. data: ['光照度']
  845. },
  846. xAxis: {
  847. type: 'time', // 使用时间类型的x轴
  848. boundaryGap: false,
  849. },
  850. yAxis: {},
  851. series: [
  852. {
  853. name: '光照度',
  854. type: 'line',
  855. data: data.map(item => [new Date(item.CreatedAt).getTime(), item.illuminance])
  856. }
  857. ],
  858. dataZoom: [
  859. {
  860. type: 'slider', // 滑动条型数据区域缩放组件
  861. start: 0, // 默认显示数据的起始百分比
  862. end: 100 // 默认显示数据的结束百分比
  863. },
  864. {
  865. type: 'inside', // 支持鼠标滚轮和双指缩放
  866. start: 0,
  867. end: 100
  868. }
  869. ]
  870. }
  871. myChart.setOption(option)
  872. }
  873. // 开关
  874. const switchButton = async(device, relay, index) => {
  875. if (index === 0) {
  876. return
  877. }
  878. await deviceSwitch({
  879. tunnelSn: device.tunnel.tunnelSn,
  880. radarId: device.radarId,
  881. relayId: relay.relayId,
  882. state: relay.state
  883. }).then(res => {
  884. if (res.code === 0) {
  885. ElMessage.success('已切换')
  886. }
  887. getData()
  888. })
  889. }
  890. // 大屏
  891. const useScreen = useScreenStore()
  892. const jumpScreen = (row) => {
  893. useScreen.setController(row)
  894. router.push('/dataDashboard')
  895. }
  896. onMounted(() => {
  897. getData()
  898. })
  899. </script>