平安校园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

758 lines
16 KiB

  1. <template>
  2. <view class="inspectionCenter">
  3. <view v-show="showVideo" class="poupBox">
  4. <view class="videoHeader">
  5. </view>
  6. <view class="contentBox">
  7. <view class="closeBox">
  8. <view class="title">
  9. {{sensorName+'(' + sensorId + ')'}}
  10. </view>
  11. <view class="closes" @click="closeDialog">
  12. <u-icon name="close-circle-fill" color="#ccc" size="22"></u-icon>
  13. </view>
  14. </view>
  15. <view class="botbox">
  16. <view id="url-player-test"></view>
  17. </view>
  18. </view>
  19. <view class="bottom-content">
  20. </view>
  21. </view>
  22. <view class="searchBox">
  23. <view class="searchLine">
  24. <view class="searchLabels" @click="showTree">
  25. <image v-show="isShowSearch==false" src="@/static/image/earlyWarning/group.png" mode="">
  26. </image>
  27. <image v-show="isShowSearch" src="@/static/image/earlyWarning/group2.png" mode="">
  28. </image>
  29. <text class="labels">选择分组</text>
  30. <view class="values">{{this.searchForm.groupName}}</view>
  31. </view>
  32. <view class="arrow">
  33. <image v-show="isShowSearch==false" src="@/static/image/earlyWarning/arrow1.png" mode="">
  34. </image>
  35. <image v-show="isShowSearch" src="@/static/image/earlyWarning/arrow2.png" mode=""></image>
  36. </view>
  37. </view>
  38. <view @click="isShowSearch=false" class="searchDialog" v-if="isShowSearch">
  39. <view class="content" @click.stop="isSelect">
  40. <u-row justify="space-between" gutter="10">
  41. <u-col span="7">
  42. <view class="demo-layout">
  43. <view class="left-layout">
  44. <text>{{'警告类型'}}</text>
  45. </view>
  46. <view class="right-layout">
  47. <image style="width: 30rpx;height:30rpx;"
  48. src="@/static/image/earlyWarning/arrowRight.png" mode=""></image>
  49. </view>
  50. </view>
  51. </u-col>
  52. <u-col span="5">
  53. <view class="demo-layout" @click="toOpenSelect">
  54. <view class="left-layout">
  55. <text>{{'处理状态'}}</text>
  56. </view>
  57. <view class="right-layout">
  58. <image style="width: 30rpx;height:30rpx;"
  59. src="@/static/image/earlyWarning/arrowRight.png" mode=""></image>
  60. </view>
  61. </view>
  62. </u-col>
  63. </u-row>
  64. <view class="btnBox">
  65. <view class="leftBtn" @click="clearform">
  66. 重置
  67. </view>
  68. <view class="rightBtn" @click="onsubmit">
  69. 确认
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. </view>
  75. <view class="tableBox">
  76. <u-empty marginTop="100rpx" :show="monitorList.length == 0&&status == 'nomore'" mode="list"
  77. text="暂无数据"></u-empty>
  78. <u-list @scrolltolower="scrolltolower" style="height: calc(100% - 0rpx);">
  79. <u-list-item v-for="(item, index) in monitorList" :key="index">
  80. <view class="liBox">
  81. <view class="topCard">
  82. <view class="pic">
  83. <image :src="item.snapshotUrl" mode="aspectFill"></image>
  84. <view class="resolvingPower">
  85. {{item.resWidth}}*{{item.resHeight}}
  86. </view>
  87. </view>
  88. <view class="rightCard">
  89. <view class="firstCard">
  90. <view class="schoolName">
  91. 摄像头ID:{{item.sensorId}}
  92. </view>
  93. </view>
  94. <view class="secondCard">
  95. <view class="txt">
  96. 摄像头名称:{{item.sensorName}}
  97. </view>
  98. </view>
  99. <view class="thirdCard">
  100. <view class="txt">
  101. 设备IP:{{item.directUrlIp}}
  102. </view>
  103. </view>
  104. <view class="thirdCard">
  105. <view class="txt">
  106. 状态:
  107. <text v-if="item.deviceStatus" style="color: #67c23a;">在线</text>
  108. <text v-else style="color: #db2777;">离线</text>
  109. </view>
  110. </view>
  111. </view>
  112. </view>
  113. <view class="btoCard">
  114. <view class="leftBox btoBox">
  115. <image src="@/static/image/earlyWarning/school.png" mode=""></image>
  116. <view class="txt">
  117. 所属学校:演示学校
  118. </view>
  119. </view>
  120. <view class="rightBox btoBox" @click="startClick(item.sensorId,item.sensorName)">
  121. <view class="txt">
  122. 播放
  123. </view>
  124. </view>
  125. </view>
  126. </view>
  127. </u-list-item>
  128. <u-loadmore :status="status" />
  129. </u-list>
  130. </view>
  131. <!-- <web-view :webview-styles="styles" src="/hybrid/html/players.html"></web-view> -->
  132. <!-- <u-modal :show="showVideo" :title="videoTitle" :closeOnClickOverlay="false" :showCancelButton="true"
  133. @confirm="confirmVideo" @cancel="cancelVideo">
  134. <view class="slot-content">
  135. <cover-view style="width: 100%;height:500px">
  136. </cover-view>
  137. </view>
  138. </u-modal> -->
  139. <tki-tree ref="tkitree" title="摄像头分组" :showChild="showChild" :selectParent="selectParent" :multiple="multiple"
  140. :range="treelist" :foldAll="flod" rangeKey="name" @confirm="treeConfirm" @cancel="treeCancel"></tki-tree>
  141. </view>
  142. </template>
  143. <script>
  144. import tkiTree from '@/components/tki-tree/tki-tree.vue';
  145. import {
  146. groupList, //获取摄像头分组
  147. list, //获取摄像头列表
  148. startUrl, //说去视频地址
  149. stopUrl //停止视频流获取
  150. } from '@/api/monitor/index.js'
  151. export default {
  152. components: {
  153. tkiTree
  154. },
  155. data() {
  156. return {
  157. styles: {
  158. width: '100%',
  159. height: '100%',
  160. zIndex: '999999999999999999999999999'
  161. // bottom: '56px'
  162. },
  163. showVideo: false,
  164. videoTitle: '',
  165. isShowSearch: false,
  166. searchForm: {
  167. groupName: '全部',
  168. groupId: '',
  169. pageNum: 1,
  170. pageSize: 10
  171. },
  172. monitorList: [],
  173. isLoading: false,
  174. status: 'loadmore', //loading正在加载 loadmore加载更多 nomore没有更多了
  175. treelist: [],
  176. multiple: false, //是否多选
  177. selectParent: true, //父级可选择
  178. flod: false, //折叠
  179. showChild: true,
  180. player: null,
  181. sensorId: '',
  182. sensorName: '',
  183. videoUrl: '',
  184. streamId: '',
  185. videoToken: '',
  186. }
  187. },
  188. watch: {
  189. },
  190. mounted() {
  191. },
  192. onLoad() {
  193. this.getGroupList()
  194. // 获取列表数据
  195. this.loadmore()
  196. },
  197. onUnload() {
  198. if (this.showVideo) {
  199. this.closeDialog()
  200. }
  201. },
  202. onPullDownRefresh() {
  203. uni.stopPullDownRefresh()
  204. this.status = 'loadmore'
  205. this.searchForm.pageNum = 1;
  206. this.monitorList = []
  207. this.loadmore()
  208. },
  209. methods: {
  210. setVideo() {
  211. let that = this;
  212. this.loadWebPlayerSDK().then(() => {
  213. // 如果需要使用自定义组件,打开以下注释
  214. // this.loadComponent().then(() => {
  215. this.player = new Aliplayer({
  216. id: "url-player-test",
  217. source: this.videoUrl + "&subaudio=no&jitterbuffer=6000",
  218. width: "100%",
  219. height: "100%",
  220. isLive: true,
  221. rtsFallback: true,
  222. rtsFallbackType: 'HLS',
  223. }, function(player) {
  224. player.mute()
  225. });
  226. this.player.one('canplay', function() {
  227. // console.log('canplay', this.player.tag);
  228. that.player.tag.play();
  229. });
  230. // }).catch((e) => { console.log("加载组件失败", e) })
  231. }).catch((e) => {
  232. console.log("加载播放器SDK失败", e);
  233. });
  234. },
  235. closeDialog() {
  236. if (this.player) {
  237. this.player.dispose();
  238. }
  239. this.showVideo = false;
  240. let params = {
  241. sensorId: this.sensorId,
  242. streamId: this.streamId,
  243. videoToken: this.videoToken
  244. };
  245. stopUrl(params).then(res => {
  246. })
  247. },
  248. loadWebPlayerSDK() {
  249. return new Promise((resolve, reject) => {
  250. const s_tag = document.createElement('script'); // 引入播放器js
  251. s_tag.type = 'text/javascript';
  252. s_tag.src = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.25.1/aliplayer-min.js'
  253. // s_tag.src = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/aliplayer-min.js';
  254. s_tag.charset = 'utf-8';
  255. s_tag.onload = () => {
  256. resolve();
  257. }
  258. document.body.appendChild(s_tag);
  259. const l_tag = document.createElement('link'); // 引入播放器css
  260. l_tag.rel = 'stylesheet';
  261. l_tag.href =
  262. 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.25.1/skins/default/aliplayer-min.css'
  263. // 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/skins/default/aliplayer-min.css';
  264. document.body.appendChild(l_tag);
  265. });
  266. },
  267. loadComponent() {
  268. return new Promise((resolve, reject) => {
  269. const s_tag = document.createElement('script');
  270. s_tag.type = 'text/javascript';
  271. // 需要先下载组件 js 文件,放到项目 /static/ 目录下
  272. // 下载地址:https://github.com/aliyunvideo/AliyunPlayer_Web/blob/master/customComponents/dist/aliplayer-components/aliplayercomponents-1.0.9.min.js
  273. s_tag.src = './static/aliplayercomponents-1.0.9.min.js';
  274. s_tag.charset = 'utf-8';
  275. s_tag.onload = () => {
  276. resolve();
  277. }
  278. document.body.appendChild(s_tag);
  279. });
  280. },
  281. addAttribute(data) { // tree结构递归添加属性
  282. for (var i = 0; i < data.length; i++) {
  283. data[i].isShow = false
  284. data[i].name = data[i].title
  285. if (data[i].children && data[i].children.length > 0) {
  286. this.addAttribute(data[i].children)
  287. }
  288. }
  289. return data
  290. },
  291. // 确定回调事件
  292. treeConfirm(e) {
  293. this.searchForm.groupName = e[0].name;
  294. this.searchForm.groupId = e[0].id;
  295. this.status = 'loadmore'
  296. this.searchForm.pageNum = 1;
  297. this.monitorList = []
  298. this.loadmore()
  299. },
  300. // 取消回调事件
  301. treeCancel(e) {
  302. // console.log(e)
  303. },
  304. // 显示树形选择器
  305. showTree() {
  306. this.$refs.tkitree._show();
  307. },
  308. cancelVideo() {
  309. this.showVideo = false;
  310. },
  311. getGroupList() {
  312. groupList({}).then((res) => {
  313. if (res.code == 200) {
  314. this.treelist = [...[{
  315. id: "",
  316. name: "全部",
  317. checked: true
  318. }], ...res.data];
  319. }
  320. });
  321. },
  322. // 获取视频地址
  323. startClick(id, name) {
  324. this.sensorId = id;
  325. this.sensorName = name;
  326. this.showVideo = true;
  327. startUrl({
  328. sensorId: id
  329. }).then(res => {
  330. let {
  331. code,
  332. data
  333. } = res;
  334. if (code == 200) {
  335. this.videoUrl = data.rtsPullStreamUrls[0].url;
  336. this.streamId = data.streamId;
  337. this.videoToken = data.videoToken;
  338. this.setVideo()
  339. }
  340. })
  341. },
  342. confirmVideo() {
  343. this.showVideo = false;
  344. },
  345. isSelect() {
  346. },
  347. scrolltolower() {
  348. if (this.status == 'loading' || this.status == 'nomore') {
  349. return;
  350. }
  351. this.searchForm.pageNum += 1;
  352. this.loadmore()
  353. },
  354. loadmore() {
  355. if (this.status != 'loadmore') return
  356. this.status = 'loading'
  357. this.isLoading = true;
  358. list(this.searchForm).then(res => {
  359. if (res?.code === 200) {
  360. this.monitorList = [...this.monitorList, ...res?.data?.list];
  361. this.isLoading = false;
  362. // 获取到的总条数>=接口总条数
  363. if (this.monitorList.length >= res.data.total) {
  364. this.status = 'nomore'
  365. } else {
  366. this.status = 'loadmore'
  367. }
  368. }
  369. })
  370. }
  371. }
  372. }
  373. </script>
  374. <style lang="scss" scoped>
  375. .container {
  376. padding: 20px;
  377. font-size: 14px;
  378. height: 800px;
  379. }
  380. // .contentBox {
  381. // height: calc(100% - 375rpx);
  382. .inspectionCenter {
  383. width: 100%;
  384. height: calc(100% - 88rpx);
  385. position: relative;
  386. .u-modal__title {
  387. color: #000000;
  388. }
  389. .poupBox {
  390. height: 100vh;
  391. position: absolute;
  392. left: 0;
  393. top: 0;
  394. width: 100%;
  395. z-index: 100000000000000;
  396. // background: red;
  397. background: rgba(0, 0, 0, 0.5);
  398. .videoHeader {
  399. height: 255rpx;
  400. }
  401. .contentBox {
  402. // z-index: 1000000;
  403. width: 100%;
  404. height: 590rpx;
  405. background: #000;
  406. // margin: 50rpx auto;
  407. .closeBox {
  408. text-align: right;
  409. height: 80rpx;
  410. display: flex;
  411. justify-content: space-between;
  412. align-items: center;
  413. padding: 0 25rpx;
  414. background: #fff;
  415. .title {
  416. font-weight: 700;
  417. font-size: 28rpx;
  418. }
  419. .closes {
  420. // background: #ccc;
  421. }
  422. }
  423. .botbox {
  424. height: calc(100% - 80rpx);
  425. }
  426. }
  427. .bottom-content {
  428. height: calc(100% - 590rpx -255rpx);
  429. }
  430. }
  431. }
  432. .searchBox {
  433. // height: calc(100% - 360rpx);
  434. position: relative;
  435. .searchLine {
  436. height: 88rpx;
  437. display: flex;
  438. align-items: center;
  439. justify-content: space-between;
  440. padding: 0 15px;
  441. box-sizing: border-box;
  442. background: #fff;
  443. font-size: 28rpx;
  444. .searchLabels {
  445. display: flex;
  446. align-items: center;
  447. width: calc(100% - 34rpx);
  448. image {
  449. width: 40rpx;
  450. height: 40rpx;
  451. flex-shrink: 1;
  452. }
  453. .labels {
  454. width: 120rpx;
  455. display: block;
  456. color: #333333;
  457. margin-left: 10rpx;
  458. flex-shrink: 1;
  459. }
  460. .values {
  461. width: calc(100% - 40rpx - 120rpx);
  462. color: #2388FF;
  463. font-weight: 700;
  464. margin-left: 18rpx;
  465. overflow: hidden;
  466. word-wrap: break-word;
  467. white-space: pre-wrap;
  468. display: -webkit-box;
  469. -webkit-box-orient: vertical;
  470. -webkit-line-clamp: 1;
  471. }
  472. }
  473. .arrow {
  474. // text-align: right;
  475. // flex-shrink: 1;
  476. image {
  477. width: 34rpx;
  478. height: 34rpx;
  479. }
  480. }
  481. .leftSearchBox {
  482. display: flex;
  483. align-items: center;
  484. width: calc(100% - 40px);
  485. .searchLabel {
  486. flex-shrink: 1;
  487. color: #333333;
  488. width: 80px;
  489. }
  490. .searchValue {
  491. width: calc(100% - 60px);
  492. margin-left: 10px;
  493. color: #2388FF;
  494. overflow: hidden;
  495. word-wrap: break-word;
  496. white-space: pre-wrap;
  497. display: -webkit-box;
  498. -webkit-box-orient: vertical;
  499. -webkit-line-clamp: 1;
  500. }
  501. }
  502. }
  503. .searchDialog {
  504. position: absolute;
  505. z-index: 990;
  506. top: 89rpx;
  507. width: 100%;
  508. height: calc(100vh - 375rpx - 100rpx);
  509. font-size: 26rpx;
  510. background: rgba(0, 0, 0, 0.2);
  511. .content {
  512. background: #FFFFFF;
  513. padding: 15px;
  514. box-sizing: border-box;
  515. border-top: 1px solid rgba(0, 0, 0, 0.1);
  516. .demo-layout {
  517. height: 80rpx;
  518. border-radius: 8rpx;
  519. background: #F5F5F5;
  520. display: flex;
  521. justify-content: space-between;
  522. align-items: center;
  523. padding: 0 10px;
  524. box-sizing: border-box;
  525. .left-layout {
  526. color: #777777;
  527. }
  528. .right-layout {}
  529. .startBox {
  530. color: #777777;
  531. }
  532. text {
  533. color: #777777;
  534. }
  535. .endBox {
  536. color: #777777;
  537. }
  538. .timeIcon {}
  539. }
  540. }
  541. .btnBox {
  542. display: flex;
  543. align-items: center;
  544. margin-top: 15px;
  545. .leftBtn {
  546. width: 50%;
  547. height: 74rpx;
  548. line-height: 74rpx;
  549. border: 1px solid #BABABA;
  550. border-radius: 12rpx;
  551. color: #333333;
  552. text-align: center;
  553. }
  554. .rightBtn {
  555. width: 50%;
  556. height: 74rpx;
  557. line-height: 74rpx;
  558. border: 1px solid #2388FF;
  559. border-radius: 12rpx;
  560. color: #fff;
  561. text-align: center;
  562. background: #2388FF;
  563. margin-left: 15rpx;
  564. }
  565. }
  566. }
  567. }
  568. .tableBox {
  569. height: 100%;
  570. padding: 0 30rpx;
  571. box-sizing: border-box;
  572. .liBox {
  573. background: #fff;
  574. padding: 24rpx 30rpx;
  575. box-sizing: border-box;
  576. border-radius: 20rpx;
  577. margin-top: 30rpx;
  578. .topCard {
  579. display: flex;
  580. align-items: center;
  581. .pic {
  582. position: relative;
  583. width: 268rpx;
  584. height: 201rpx;
  585. image {
  586. width: 268rpx;
  587. height: 201rpx;
  588. border-radius: 4px;
  589. }
  590. .resolvingPower {
  591. position: absolute;
  592. top: 15rpx;
  593. right: 15rpx;
  594. background: #000000;
  595. color: #fff;
  596. padding: 8rpx;
  597. box-sizing: border-box;
  598. font-size: 20rpx;
  599. border-radius: 4rpx;
  600. font-family: 'PingFang SC';
  601. }
  602. }
  603. .rightCard {
  604. margin-left: 20rpx;
  605. .firstCard {
  606. display: flex;
  607. justify-content: space-between;
  608. align-items: center;
  609. // margin-bottom: 60rpx;
  610. .schoolName {
  611. font-size: 32rpx;
  612. font-family: 'PingFang SC';
  613. font-weight: 700;
  614. color: #333333;
  615. overflow: hidden;
  616. word-wrap: break-word;
  617. white-space: pre-wrap;
  618. // font-size: 14px;
  619. display: -webkit-box;
  620. -webkit-box-orient: vertical;
  621. -webkit-line-clamp: 1;
  622. }
  623. }
  624. .secondCard,
  625. .thirdCard {
  626. display: flex;
  627. align-items: center;
  628. margin-top: 16rpx;
  629. .txt {
  630. font-size: 26rpx;
  631. font-family: 'PingFang SC';
  632. color: #333333;
  633. }
  634. }
  635. }
  636. }
  637. .btoCard {
  638. border-top: 1px solid rgba(0, 0, 0, 0.1);
  639. margin-top: 24rpx;
  640. padding: 24rpx 0 0 0;
  641. display: flex;
  642. justify-content: space-between;
  643. align-items: center;
  644. .btoBox {
  645. // width: 33.3%;
  646. display: flex;
  647. justify-content: center;
  648. align-items: center;
  649. position: relative;
  650. font-size: 26rpx;
  651. color: #333;
  652. font-family: 'PingFang SC';
  653. image {
  654. width: 36rpx;
  655. height: 36rpx;
  656. margin-right: 15rpx;
  657. }
  658. }
  659. .rightBox {
  660. width: 120rpx;
  661. height: 60rpx;
  662. background: #2388FF;
  663. color: #fff;
  664. border-radius: 80rpx;
  665. }
  666. }
  667. }
  668. }
  669. // }
  670. </style>