right.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. <template>
  2. <el-aside class="right">
  3. <div class="right_top">
  4. <div class="title" :style="{ background: `url(${frame})` }">
  5. <div class="text">物联设备统计</div>
  6. </div>
  7. <div class="content">
  8. <div class="logo">
  9. <span>{{ equipmentTotal.total }}</span>
  10. <img class="animate" :src="d1img" alt="" />
  11. <img :src="d12img" alt="" />
  12. <span><b>总数</b>(个)</span>
  13. </div>
  14. <div class="list">
  15. <div class="item_r">
  16. <img :src="d2img" alt="" />
  17. <div
  18. class="percent"
  19. style="display: flex; justify-content: space-between"
  20. >
  21. <a>在线</a> <a>{{ equipmentTotal.online }} <span>(个)</span> </a>
  22. </div>
  23. </div>
  24. <div class="item_r">
  25. <img :src="d3img" alt="" />
  26. <div
  27. class="percent"
  28. style="display: flex; justify-content: space-between"
  29. >
  30. <a>离线</a>
  31. <a>{{ equipmentTotal.underline }} <span>(个)</span> </a>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. <div class="right_center">
  38. <div class="title" :style="{ background: `url(${frame})` }">
  39. <div class="text">物联设备类型统计</div>
  40. </div>
  41. <div class="contentwrap">
  42. <div class="count" v-for="(item, index) in interDevice" :key="index">
  43. <countTo
  44. :startVal="0"
  45. :endVal="item.number"
  46. :decimals="0"
  47. :duration="3000"
  48. ></countTo>
  49. <img :src="deviceImg + item.icon + '.png'" alt="" />
  50. <div class="text">{{ item?.text }}</div>
  51. </div>
  52. </div>
  53. </div>
  54. <div class="right_bottom">
  55. <div class="title" :style="{ background: `url(${frame})` }">
  56. <div class="text">教室实时监控</div>
  57. </div>
  58. <!-- <div class="monitorContent" :style="{ background: `url(${videoBorder})` }"> -->
  59. <div class="monitorContent">
  60. <img
  61. @click="swiperRef.prev()"
  62. class="change-left"
  63. :src="swiperLeft"
  64. alt=""
  65. srcset=""
  66. />
  67. <el-carousel
  68. class="swiper-container"
  69. ref="swiperRef"
  70. :autoplay="false"
  71. indicator-position="none"
  72. @change="monitorchange"
  73. arrow="never"
  74. >
  75. <!-- <img src="swiper-left" alt="" srcset=""> -->
  76. <el-carousel-item
  77. v-for="(item, index) in carouselData"
  78. :key="index"
  79. @click="lookVideo(item)"
  80. style="height: 100%"
  81. >
  82. <p style="margin-left: 12px; margin-bottom: 3px; font-size: 14px">
  83. {{ item.title }}
  84. </p>
  85. <div class="video-container" v-if="videoindex == index">
  86. <VideoJs
  87. style="height: 100%"
  88. class="video"
  89. :videoSrc="item.src"
  90. autoPlay
  91. />
  92. </div>
  93. </el-carousel-item>
  94. </el-carousel>
  95. <img
  96. class="video-border"
  97. style="height: 100%; width: 100%"
  98. :src="videoBorder"
  99. alt=""
  100. srcset=""
  101. />
  102. <img
  103. @click="swiperRef.next()"
  104. class="change-right"
  105. :src="swiperRight"
  106. alt=""
  107. srcset=""
  108. />
  109. </div>
  110. </div>
  111. </el-aside>
  112. <!-- 视频播放弹框 -->
  113. <el-dialog
  114. class="videoDialog"
  115. v-model="videoDialog"
  116. :title="dialogTitle"
  117. width="62%"
  118. align="center"
  119. top="8%"
  120. style="z-index: 2015; padding: 0"
  121. >
  122. <videoPlay v-bind="videoData" />
  123. <!-- {{ videoData.src }} -->
  124. </el-dialog>
  125. <el-dialog
  126. custom-class="deviceDialog"
  127. v-model="deviceDialog"
  128. title="设备明细"
  129. width="40%"
  130. align="left"
  131. top="30vh"
  132. style="z-index: 2015; background: rgba(0, 0, 0, 0)"
  133. >
  134. <el-table
  135. :data="deviceDetailsList"
  136. border
  137. height="100%"
  138. style="width: 100%; background: rgba(0, 0, 0, 0)"
  139. >
  140. <el-table-column
  141. align="center"
  142. type="index"
  143. label="序号"
  144. ></el-table-column>
  145. <el-table-column
  146. align="center"
  147. prop="name"
  148. label="设备名称"
  149. ></el-table-column>
  150. <el-table-column align="center" prop="status" label="设备状态">
  151. <template #default="scope">
  152. <div
  153. :class="{
  154. normal: scope.row.status == '正常',
  155. error: scope.row.status == '异常',
  156. }"
  157. >
  158. <div>{{ scope.row.status }}</div>
  159. </div>
  160. </template>
  161. </el-table-column>
  162. <el-table-column label="操作" align="center">
  163. <template #default="scope">
  164. <el-button type="primary" size="mini" @click="lookDetails(scope.row)"
  165. >详情</el-button
  166. >
  167. </template>
  168. </el-table-column>
  169. </el-table>
  170. <el-dialog
  171. custom-class="deviceDetailsDialog"
  172. v-model="isShowDeviceDetails"
  173. title="详情"
  174. width="15%"
  175. align="left"
  176. top="40vh"
  177. style="z-index: 2019; background: rgba(0, 0, 0, 0)"
  178. :modal="false"
  179. >
  180. <div class="details-container">
  181. <div>设备名称:多媒体设备</div>
  182. <div>设备状态:<span :style="{ online: true }">在线</span></div>
  183. <div>位置:一号教学楼A101</div>
  184. <div>型号:教学设备</div>
  185. <div>质保期:5年</div>
  186. </div>
  187. </el-dialog>
  188. </el-dialog>
  189. </template>
  190. <script >
  191. import { reactive, onBeforeMount, ref, nextTick, onMounted } from "vue";
  192. import { ElCarousel, ElCarouselItem } from "element-plus";
  193. import "vue3-video-play/dist/style.css";
  194. import { videoPlay } from "vue3-video-play";
  195. // import CircleProgress from './CircleProgress.vue';
  196. import { getDevice, getVideoUrl, getvideo } from "../request/api";
  197. //找到你的组件地址引入进来
  198. import VideoJs from "./VideoJs.vue";
  199. import { CountTo } from "vue3-count-to";
  200. export default {
  201. name: "Histogram",
  202. components: {
  203. videoPlay,
  204. ElCarousel,
  205. ElCarouselItem,
  206. CountTo,
  207. VideoJs,
  208. },
  209. setup() {
  210. onMounted(() => {});
  211. const data = reactive({
  212. videoSrc:
  213. "http://kbs-dokdo.gscdn.com/dokdo_300/_definst_/dokdo_300.stream/playlist.m3u8",
  214. });
  215. // 视频数据
  216. const videoData = reactive({
  217. width: "100%", //播放器高度
  218. height: "66.5vh", //播放器高度
  219. color: "red", //主题色
  220. // title: "互动教室", //视频名称
  221. // src: "https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/IronMan.mp4", //视频源
  222. src: "https://scpull04.scjtonline.cn/scgro4/C436715B032077D498730AC93826DE29.m3u8?t=67c9399e&k=fe0359a57220382aa6a8bc859e918ade",
  223. type: "m3u8",
  224. muted: true, //静音
  225. webFullScreen: false,
  226. // speedRate: ["0.75", "1.0", "1.25", "1.5", "2.0"], //播放倍速
  227. autoPlay: true, //自动播放
  228. loop: false, //循环播放
  229. mirror: false, //镜像画面
  230. ligthOff: false, //关灯模式
  231. volume: 0.3, //默认音量大小
  232. control: true, //是否显示控制
  233. currentTime: 0, //跳转到固定播放时间
  234. controlBtns: [
  235. "audioTrack",
  236. "quality",
  237. "speedRate",
  238. "volume",
  239. "setting",
  240. "pip",
  241. "pageFullScreen",
  242. "fullScreen",
  243. ], //显示所有按钮,
  244. });
  245. //视频播放弹框
  246. const videoDialog = ref(false);
  247. const asd = ref(false);
  248. //播放视频索引
  249. let videoindex = ref(0);
  250. let monitorchange = function (val) {
  251. // let videos = document.querySelectorAll('.interactclass video');
  252. // setTimeout(() => {
  253. // for (let video of videos) {
  254. // console.log("sbdadbdbdb",video);
  255. // video.pause();
  256. // video.removeAttribute('src'); // empty source
  257. // video.load();
  258. // // video.remove();
  259. // video.destroy();
  260. // video.load();
  261. // video.scr='';
  262. // video.style.display = 'none';
  263. // video=null;
  264. // // video.dispose();
  265. // }
  266. // }, 500);
  267. setTimeout(() => {
  268. videoindex.value = val;
  269. }, 500);
  270. };
  271. // const videoshow = ref(true)
  272. const dialogTitle = ref("");
  273. // 播放视频
  274. const lookVideo = function (item) {
  275. console.log("item", item);
  276. videoDialog.value = true;
  277. dialogTitle.value = item.title;
  278. getVideoUrl({ rtsp: item.src }).then((res) => {
  279. console.log("视频处理", res);
  280. console.log("视频处理2", res.data.httpFlv);
  281. videoData.src = res.data.httpFlv;
  282. });
  283. // videoData.src = src;
  284. // videoData.src =
  285. // "https://weizhi.huanghuai.edu.cn/jk/hls/c7a1e790-b3bc-4092-a975-40d0e35d54c2.m3u8";
  286. };
  287. // 播放视频
  288. const onPlay = function () {
  289. console.log("播放视频");
  290. };
  291. // 物联设备
  292. let equipmentTotal = ref({});
  293. // 物联设备类型统计
  294. let interDevice = ref([]);
  295. // 智慧教室
  296. let carouselData = ref([]);
  297. //获取页面数据
  298. const getDeviceData = async () => {
  299. //视频转码
  300. // getvideo({
  301. // "rtsp": "rtsp://admin:admin@10.116.255.67:554",
  302. // }).then((res)=>{
  303. // console.log('sadnuq21',res);
  304. // })
  305. let res = await getDevice();
  306. if (res.code !== 200) {
  307. ElMessage.error("数据请求出错");
  308. }
  309. let { category, monitor, status } = res.data;
  310. //物联设备统计
  311. equipmentTotal.value = status;
  312. // 物联设备类型数据
  313. console.log("sadui12u31", category);
  314. //截取数组前6项
  315. interDevice.value = category;
  316. // monitor.map((res) => {
  317. // console.log('sadhi2', res.activeMonitor);
  318. // if(res.activeMonitor.array){
  319. // res.activeMonitor.array.map(array => {
  320. // //视频转码
  321. // getvideo({
  322. // "rtsp": array.src,
  323. // }).then((res) => {
  324. // // array.src = 'http://kbs-dokdo.gscdn.com/dokdo_300/_definst_/dokdo_300.stream/playlist.m3u8'
  325. // array.src=res.data.httpFlv
  326. // })
  327. // })
  328. // }
  329. // if ( res.activeMonitor.array1) {
  330. // res.activeMonitor.array1.map(array1 => {
  331. // //视频转码
  332. // getvideo({
  333. // "rtsp": array1.src,
  334. // }).then((res) => {
  335. // // array1.src = 'http://kbs-dokdo.gscdn.com/dokdo_300/_definst_/dokdo_300.stream/playlist.m3u8'
  336. // array1.src=res.data.httpFlv
  337. // })
  338. // })
  339. // }
  340. // })
  341. // 互动教室
  342. carouselData.value = monitor;
  343. console.log("hshshhs", carouselData.value);
  344. };
  345. onBeforeMount(() => {
  346. getDeviceData();
  347. setTimeout(() => {
  348. asd.value = true;
  349. }, 1000);
  350. });
  351. let deviceDialog = ref(false);
  352. const showDeviceDialog = () => {
  353. deviceDialog.value = true;
  354. };
  355. let deviceDetailsList = ref([
  356. {
  357. name: "多媒体设备",
  358. status: "正常",
  359. },
  360. {
  361. name: "多媒体设备",
  362. status: "异常",
  363. },
  364. ]);
  365. let isShowDeviceDetails = ref(false);
  366. const lookDetails = (data) => {
  367. console.log("darta", data);
  368. isShowDeviceDetails.value = true;
  369. };
  370. let swiperRef = ref(null);
  371. const d1img = ref("./img/d1_1.png");
  372. const d12img = ref("./img/d1_2.png");
  373. const d2img = ref("./img/d2.png");
  374. const d3img = ref("./img/d3.png");
  375. const deviceImg = ref("./img/");
  376. const frame = ref("./img/frame.png");
  377. const videoBorder = ref("./img/video-border.png");
  378. const swiperLeft = ref("./img/swiper-left.png");
  379. const swiperRight = ref("./img/swiper-right.png");
  380. return {
  381. interDevice,
  382. videoData,
  383. onPlay,
  384. videoDialog,
  385. lookVideo,
  386. carouselData,
  387. equipmentTotal,
  388. d1img,
  389. d12img,
  390. d2img,
  391. d3img,
  392. deviceImg,
  393. dialogTitle,
  394. monitorchange,
  395. videoindex,
  396. data,
  397. asd,
  398. frame,
  399. videoBorder,
  400. deviceDialog,
  401. deviceDetailsList,
  402. lookDetails,
  403. isShowDeviceDetails,
  404. swiperLeft,
  405. swiperRight,
  406. swiperRef,
  407. };
  408. },
  409. };
  410. </script>
  411. <style scoped lang="scss">
  412. @import "../assets/css/right.scss";
  413. </style>
  414. <style lang="scss" >
  415. .videoDialog {
  416. .el-dialog__header {
  417. height: 49px;
  418. line-height: 49px;
  419. padding: 0;
  420. background-color: #1b67d9;
  421. margin-right: 0;
  422. .el-dialog__title {
  423. color: #fff;
  424. font-family: Inter;
  425. }
  426. .el-dialog__headerbtn {
  427. top: 0px;
  428. i {
  429. color: #fff;
  430. font-size: 20px;
  431. font-weight: bold;
  432. }
  433. }
  434. }
  435. .el-dialog__body {
  436. padding: 0 !important;
  437. }
  438. }
  439. .deviceDialog {
  440. .el-dialog__header {
  441. height: 39px;
  442. line-height: 39px;
  443. padding: 0;
  444. background-color: #1b67d9;
  445. margin-right: 0;
  446. text-indent: 14px;
  447. .el-dialog__title {
  448. color: #fff;
  449. font-family: Inter;
  450. }
  451. .el-dialog__headerbtn {
  452. top: 0px;
  453. i {
  454. color: #fff;
  455. font-size: 20px;
  456. font-weight: bold;
  457. }
  458. }
  459. }
  460. .el-dialog__body {
  461. // padding: 10px !important;
  462. background-color: rgba(0, 0, 0, 0.5) !important;
  463. .el-table {
  464. --el-table-border-color: #253f48;
  465. --el-table-row-hover-bg-color: rgba(0, 0, 0, 0.7);
  466. .normal {
  467. text-align: center;
  468. /* text/pc/02-55-Regular */
  469. font-family: "Alibaba PuHuiTi 2.0";
  470. font-size: 14px;
  471. font-style: normal;
  472. font-weight: 400;
  473. line-height: normal;
  474. display: flex;
  475. justify-content: center;
  476. align-items: center;
  477. div {
  478. width: 50px;
  479. height: 26px;
  480. background-color: #0b4935;
  481. // line-height: 30px;
  482. line-height: 26px;
  483. color: #13eb7f;
  484. box-sizing: border-box;
  485. border-radius: 4px;
  486. // padding: 4px 6px;
  487. }
  488. }
  489. .error {
  490. text-align: center;
  491. /* text/pc/02-55-Regular */
  492. font-family: "Alibaba PuHuiTi 2.0";
  493. font-size: 14px;
  494. font-style: normal;
  495. font-weight: 400;
  496. line-height: normal;
  497. display: flex;
  498. justify-content: center;
  499. align-items: center;
  500. div {
  501. width: 50px;
  502. height: 26px;
  503. background-color: #442124;
  504. // line-height: 30px;
  505. line-height: 26px;
  506. color: #ff352e;
  507. box-sizing: border-box;
  508. border-radius: 4px;
  509. // padding: 4px 6px;
  510. }
  511. }
  512. }
  513. .el-table th.el-table__cell {
  514. background-color: rgba(0, 0, 0, 0.5);
  515. }
  516. .el-table tr {
  517. background-color: rgba(0, 0, 0, 0.5);
  518. }
  519. .el-table td.el-table__cell,
  520. .el-table th.el-table__cell.is-leaf {
  521. border-color: #253f48;
  522. }
  523. }
  524. }
  525. .deviceDetailsDialog {
  526. .el-dialog__header {
  527. height: 39px;
  528. line-height: 39px;
  529. padding: 0px;
  530. background-color: #1b67d9;
  531. margin-right: 0;
  532. text-indent: 10px;
  533. .el-dialog__title {
  534. color: #fff;
  535. font-family: Inter;
  536. }
  537. .el-dialog__headerbtn {
  538. top: 0px;
  539. i {
  540. color: #fff;
  541. font-size: 20px;
  542. font-weight: bold;
  543. }
  544. }
  545. }
  546. .el-dialog__body {
  547. padding: 10px !important;
  548. background-color: rgba(0, 0, 0, 0.2) !important;
  549. .details-container {
  550. color: #fff;
  551. /* text/pc/03-55-Regular */
  552. font-family: "Alibaba PuHuiTi 2.0";
  553. font-size: 12px;
  554. font-style: normal;
  555. font-weight: 400;
  556. line-height: normal;
  557. line-height: 30px;
  558. .online {
  559. color: #30fcaa !important;
  560. }
  561. }
  562. }
  563. }
  564. .el-tag .el-tag--success {
  565. --el-tag-text-color: #000;
  566. }
  567. .d-player-video {
  568. display: flex;
  569. }
  570. .el-drawer {
  571. background-color: transparent !important;
  572. padding: 0px !important;
  573. box-shadow: none !important;
  574. }
  575. </style>