index.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. <template>
  2. <div class="inspection">
  3. <div class="left">
  4. <div class="tree">
  5. <monitorList
  6. @getClickId="getClickId"
  7. @getCameraList="getCameraList"
  8. ></monitorList>
  9. </div>
  10. </div>
  11. <div class="center">
  12. <div class="monitor">
  13. <el-carousel
  14. ref="carouselRef"
  15. indicator-position="outside"
  16. style="height: calc(100% - 42px)"
  17. :autoplay="false"
  18. trigger="click"
  19. @change="carouselChange"
  20. >
  21. <el-carousel-item
  22. v-for="(page, pageIndex) in pageNum"
  23. :key="pageIndex"
  24. >
  25. <div class="page" v-loading="loading">
  26. <div
  27. :style="itemStyle"
  28. v-for="(video, videoIndex) in itemNum(pageIndex)"
  29. :key="videoIndex"
  30. >
  31. <div
  32. v-if="pageIndex == carouselIndex"
  33. style="width: 100%; height: 100%"
  34. @click="
  35. deviceCode =
  36. videoList[pageIndex * layout * layout + videoIndex][
  37. 'cameraCode'
  38. ]
  39. "
  40. :class="{
  41. active:
  42. deviceCode ==
  43. videoList[pageIndex * layout * layout + videoIndex][
  44. 'cameraCode'
  45. ]
  46. }"
  47. class="box-border videoItem"
  48. >
  49. <!-- <myVideo
  50. :video-url="
  51. videoList[pageIndex * layout * layout + videoIndex]['url']
  52. "
  53. :index="pageIndex * layout * layout + videoIndex"
  54. /> -->
  55. <myVideo
  56. :autoplay="true"
  57. :muted="true"
  58. :width="960"
  59. :height="540"
  60. :isLive="true"
  61. show-reload-btn
  62. @setLoading="setLoading"
  63. :video-url="
  64. videoList[pageIndex * layout * layout + videoIndex]['url']
  65. "
  66. />
  67. <div class="mask1">
  68. <img
  69. @click.stop="
  70. handleScreenshot(
  71. pageIndex * layout * layout + videoIndex,
  72. $event
  73. )
  74. "
  75. :src="
  76. require('@/assets/svgs/centerctl/videoSur/camera.svg')
  77. "
  78. />
  79. </div>
  80. <div
  81. class="mask2"
  82. v-if="
  83. stopList.includes(
  84. pageIndex * layout * layout + videoIndex
  85. )
  86. "
  87. >
  88. <img
  89. class="play"
  90. @click.stop="
  91. play(pageIndex * layout * layout + videoIndex)
  92. "
  93. :src="
  94. require('@/assets/svgs/centerctl/videoSur/play.svg')
  95. "
  96. alt=""
  97. />
  98. </div>
  99. </div>
  100. </div>
  101. </div>
  102. </el-carousel-item>
  103. </el-carousel>
  104. <div class="center-handle">
  105. <div
  106. class="layout-type"
  107. id="layout"
  108. @click="getFocus"
  109. @blur="blur"
  110. tabindex="0"
  111. >
  112. <div style="width: 100%; height: 100%" @click="toggle" tabindex="0">
  113. <div class="layout">
  114. <div
  115. v-for="(item, index) in layout * layout"
  116. :key="index"
  117. :style="{
  118. width: `calc((100% - 1px * (${layout} - 1)) / ${layout})`,
  119. height: `calc((100% - 1px * (${layout} - 1)) / ${layout})`,
  120. backgroundColor: '#404446'
  121. }"
  122. ></div>
  123. </div>
  124. <i class="el-icon-caret-bottom"></i>
  125. </div>
  126. <div class="group" v-show="isShow">
  127. <div
  128. class="layout"
  129. v-show="index + 1 != layout"
  130. v-for="(item, index) in maxLayout"
  131. :key="index"
  132. >
  133. <div
  134. @click="choose(index)"
  135. v-for="n in (index + 1) * (index + 1)"
  136. :key="n"
  137. :style="{
  138. width: `calc((100% - 1px * (${index + 1} - 1)) / ${
  139. index + 1
  140. })`,
  141. height: `calc((100% - 1px * (${index + 1} - 1)) / ${
  142. index + 1
  143. })`,
  144. backgroundColor: '#404446'
  145. }"
  146. ></div>
  147. </div>
  148. </div>
  149. </div>
  150. <div class="play">
  151. <el-tooltip
  152. class="item"
  153. effect="dark"
  154. content="第一个"
  155. placement="top"
  156. >
  157. <img
  158. @click="home"
  159. :src="require('@/assets/svgs/centerctl/videoSur/last.svg')"
  160. alt=""
  161. />
  162. </el-tooltip>
  163. <el-tooltip
  164. class="item"
  165. effect="dark"
  166. content="上一个"
  167. placement="top"
  168. >
  169. <img
  170. @click="last"
  171. :src="
  172. require('@/assets/svgs/centerctl/videoSur/fast-backward.svg')
  173. "
  174. alt=""
  175. />
  176. </el-tooltip>
  177. <el-tooltip
  178. class="item"
  179. effect="dark"
  180. content="播放/暂停"
  181. placement="top"
  182. >
  183. <img
  184. @click="playStop"
  185. :src="require('@/assets/svgs/centerctl/videoSur/play-stop.svg')"
  186. alt=""
  187. />
  188. </el-tooltip>
  189. <el-tooltip
  190. class="item"
  191. effect="dark"
  192. content="下一个"
  193. placement="top"
  194. >
  195. <img
  196. @click="next"
  197. :src="
  198. require('@/assets/svgs/centerctl/videoSur/fast-forward.svg')
  199. "
  200. alt=""
  201. />
  202. </el-tooltip>
  203. <el-tooltip
  204. class="item"
  205. effect="dark"
  206. content="最后一个"
  207. placement="top"
  208. >
  209. <img
  210. @click="end"
  211. :src="require('@/assets/svgs/centerctl/videoSur/next.svg')"
  212. alt=""
  213. />
  214. </el-tooltip>
  215. </div>
  216. <div class="video-handle">
  217. <img
  218. :src="require('@/assets/svgs/centerctl/videoSur/volume-x.svg')"
  219. alt=""
  220. />
  221. <img
  222. :src="require('@/assets/svgs/centerctl/videoSur/big.svg')"
  223. alt=""
  224. />
  225. </div>
  226. </div>
  227. </div>
  228. </div>
  229. <div style="height: 100%; padding: 0">
  230. <div class="deviceInfo">
  231. <div class="frame-48095487">
  232. <div class="div">设备信息</div>
  233. </div>
  234. <div class="row">
  235. <div class="div">摄像机名称</div>
  236. <div class="name">{{ camera.name }}</div>
  237. </div>
  238. <div class="row">
  239. <div class="div">摄像机编号</div>
  240. <div class="div">{{ camera.deviceCode }}</div>
  241. </div>
  242. <div class="row">
  243. <div class="div">设备品牌</div>
  244. <div class="div">{{ camera.brandName }}</div>
  245. </div>
  246. <div class="row">
  247. <div class="div">设备型号</div>
  248. <div class="div">{{ camera.modelName }}</div>
  249. </div>
  250. </div>
  251. <div class="handle">
  252. <direction @handle="handle" />
  253. <div class="slider">
  254. <el-slider
  255. v-model="slider"
  256. :min="1"
  257. :max="7"
  258. style="width: 154px"
  259. ></el-slider>
  260. <div class="sliderNum">{{ slider }}</div>
  261. </div>
  262. <div class="moreHandle">
  263. <div class="row">
  264. <div class="item normal">
  265. <el-tooltip effect="dark" content="开关灯" placement="top">
  266. <img
  267. :src="
  268. require('@/assets/svgs/isp/ispRealTime/video/light.svg')
  269. "
  270. alt=""
  271. @click="switchLamp(camera.deviceCode)"
  272. />
  273. </el-tooltip>
  274. </div>
  275. <div class="item">
  276. <img
  277. :src="require('@/assets/svgs/isp/ispRealTime/video/yushua.svg')"
  278. alt=""
  279. />
  280. </div>
  281. <div class="item">
  282. <img
  283. :src="require('@/assets/svgs/isp/ispRealTime/video/jvjiao.svg')"
  284. alt=""
  285. />
  286. </div>
  287. <div class="item">
  288. <img
  289. :src="
  290. require('@/assets/svgs/isp/ispRealTime/video/chushihua.svg')
  291. "
  292. alt=""
  293. />
  294. </div>
  295. <div class="item">
  296. <img
  297. :src="require('@/assets/svgs/isp/ispRealTime/video/menu.svg')"
  298. alt=""
  299. />
  300. </div>
  301. </div>
  302. <div class="line"></div>
  303. <div class="row">
  304. <div class="item normal" v-loading="screenshotVal">
  305. <el-tooltip effect="dark" content="截图" placement="top">
  306. <img
  307. @click="screenshot(camera.deviceCode)"
  308. :src="require('@/assets/svgs/isp/ispRealTime/video/cw.svg')"
  309. alt=""
  310. />
  311. </el-tooltip>
  312. </div>
  313. <div class="item">
  314. <img
  315. :src="require('@/assets/svgs/isp/ispRealTime/video/3d.svg')"
  316. alt=""
  317. />
  318. </div>
  319. <div class="item"></div>
  320. <div class="item"></div>
  321. <div class="item"></div>
  322. </div>
  323. </div>
  324. <PresetPositions
  325. :PresetList="PresetList"
  326. :deviceCode="deviceCode"
  327. @getPreset="getPreset"
  328. ></PresetPositions>
  329. </div>
  330. </div>
  331. </div>
  332. </template>
  333. <script>
  334. import PresetPositions from './components/Preset-positions.vue';
  335. import monitorList from './components/monitorList.vue';
  336. import direction from './components/direction.vue';
  337. import myVideo from '../components/video.vue';
  338. import * as realTime from '@/api/isp/ispRealtime/monitor/index';
  339. import * as deviceApi from '@/api/isp/deviceManage/robot';
  340. // import FLVPlayer from "./FLVPlayer.vue";
  341. export default {
  342. name: 'MonitorPage',
  343. components: {
  344. PresetPositions,
  345. monitorList,
  346. direction,
  347. myVideo
  348. },
  349. data() {
  350. return {
  351. layout: 1,
  352. loading: false,
  353. videoList: [],
  354. carouselIndex: 0,
  355. isShow: false,
  356. deviceCode: undefined,
  357. camera: {},
  358. stopList: [],
  359. slider: 1,
  360. screenshotVal: false,
  361. PresetList: [],
  362. codeList: [],
  363. monitorData: []
  364. };
  365. },
  366. beforeDestroy() {
  367. if (this.deviceCode) {
  368. realTime.delStreamProxy(this.deviceCode);
  369. }
  370. },
  371. computed: {
  372. maxLayout() {
  373. if (this.videoList.length > 8) {
  374. return 4;
  375. } else if (this.videoList.length > 3) {
  376. return 3;
  377. } else if (this.videoList.length > 1) {
  378. return 2;
  379. } else {
  380. return 1;
  381. }
  382. },
  383. count() {
  384. return this.videoList.length;
  385. },
  386. pageNum() {
  387. let num = this.count / (this.layout * this.layout);
  388. return Math.ceil(num);
  389. },
  390. itemStyle() {
  391. return {
  392. width: `calc((100% - 10px * (${this.layout} - 1)) / ${this.layout})`,
  393. height: `calc((100% - 10px * (${this.layout} - 1)) / ${this.layout})`
  394. };
  395. }
  396. },
  397. watch: {
  398. deviceCode(val, oldVal) {
  399. if (oldVal) {
  400. realTime.delStreamProxy(oldVal);
  401. }
  402. this.getPreset();
  403. }
  404. },
  405. mounted() {},
  406. methods: {
  407. setLoading(loading) {
  408. this.loading = loading;
  409. },
  410. itemNum(pageIndex) {
  411. if (this.pageNum != 1 && pageIndex == this.pageNum - 1) {
  412. return this.count - this.layout * this.layout * (this.pageNum - 1);
  413. } else if (this.pageNum == 1) {
  414. return this.count;
  415. } else {
  416. return this.layout * this.layout;
  417. }
  418. },
  419. carouselChange(index) {
  420. this.carouselIndex = index;
  421. if (this.layout == 1) this.getClickId(this.monitorData[index]);
  422. },
  423. toggle(e) {
  424. this.isShow = !this.isShow;
  425. },
  426. getFocus() {
  427. const layout = document.getElementById('layout');
  428. if (layout) layout.focus();
  429. },
  430. blur() {
  431. this.isShow = false;
  432. },
  433. choose(index) {
  434. this.layout = index + 1;
  435. this.isShow = false;
  436. },
  437. home() {
  438. this.carouselIndex = 0;
  439. this.$refs.carouselRef && this.$refs.carouselRef.setActiveItem(0);
  440. },
  441. last() {
  442. if (this.carouselIndex > 0) {
  443. this.carouselIndex--;
  444. this.$refs.carouselRef &&
  445. this.$refs.carouselRef.setActiveItem(this.carouselIndex);
  446. } else {
  447. this.carouselIndex = this.pageNum - 1;
  448. this.$refs.carouselRef &&
  449. this.$refs.carouselRef.setActiveItem(this.pageNum - 1);
  450. }
  451. },
  452. next() {
  453. if (this.carouselIndex < this.pageNum - 1) {
  454. this.carouselIndex++;
  455. this.$refs.carouselRef &&
  456. this.$refs.carouselRef.setActiveItem(this.carouselIndex);
  457. } else {
  458. this.carouselIndex = 0;
  459. this.$refs.carouselRef && this.$refs.carouselRef.setActiveItem(0);
  460. }
  461. },
  462. end() {
  463. this.carouselIndex = this.pageNum - 1;
  464. this.$refs.carouselRef &&
  465. this.$refs.carouselRef.setActiveItem(this.pageNum - 1);
  466. },
  467. handleScreenshot(index, e) {
  468. const videoPlayback = document.getElementById('video' + index);
  469. if (!videoPlayback) return;
  470. const canvas = document.createElement('canvas');
  471. canvas.width = videoPlayback.videoWidth;
  472. canvas.height = videoPlayback.videoHeight;
  473. const ctx = canvas.getContext('2d');
  474. if (ctx) {
  475. ctx.drawImage(videoPlayback, 0, 0, canvas.width, canvas.height);
  476. }
  477. const img = new Image();
  478. img.src = canvas.toDataURL('image/png');
  479. const a = document.createElement('a');
  480. a.href = img.src;
  481. a.download = 'screenshot.png';
  482. document.body.appendChild(a);
  483. a.click();
  484. document.body.removeChild(a);
  485. e.stopPropagation();
  486. },
  487. async handle(SDK) {
  488. if (SDK == 'reset') {
  489. let params = {
  490. cameraCode: this.deviceCode,
  491. wPresetNum: 34,
  492. command: 'GOTO_PRESET'
  493. };
  494. const res = await realTime.oprPreset(params);
  495. if (res == 'SUCCESS') {
  496. this.$message.success('操作成功');
  497. } else {
  498. this.$message.error(res);
  499. }
  500. return;
  501. }
  502. let res = await realTime.playControl({
  503. cameraCode: this.deviceCode,
  504. mill: this.slider * 1000,
  505. command: SDK
  506. });
  507. if (res == 'SUCCESS') {
  508. this.$message.success('操作成功');
  509. } else {
  510. this.$message.error(res);
  511. }
  512. },
  513. async switchLamp(code) {
  514. if (!code) return this.$message.warning('当前设备异常');
  515. const data = await deviceApi.playControl({
  516. cameraCode: code,
  517. mill: 1000,
  518. command: 'LIGHT_PWRON'
  519. });
  520. if (data == 'SUCCESS') {
  521. this.$message.success('指令下发成功');
  522. } else {
  523. this.$message.error('指令下发失败');
  524. }
  525. },
  526. async screenshot(code) {
  527. if (!code) return this.$message.warning('当前设备异常');
  528. this.screenshotVal = true;
  529. try {
  530. const data = await deviceApi.catchPic(code);
  531. if (data.size < 100) {
  532. this.$message.warning('截图失败');
  533. } else {
  534. const dlink = document.createElement('a');
  535. dlink.download = '截图.png';
  536. dlink.style.display = 'none';
  537. dlink.href = URL.createObjectURL(data);
  538. document.body.appendChild(dlink);
  539. dlink.click();
  540. URL.revokeObjectURL(dlink.href);
  541. document.body.removeChild(dlink);
  542. this.$message.success('截图下载成功');
  543. }
  544. } finally {
  545. this.screenshotVal = false;
  546. }
  547. },
  548. playStop() {
  549. let index = Math.floor(
  550. this.videoList.findIndex(
  551. (item) => item.cameraCode == this.deviceCode
  552. ) /
  553. (this.layout * this.layout)
  554. );
  555. let videoElement = document.getElementById('video' + index);
  556. if (videoElement && videoElement.paused) {
  557. videoElement.play();
  558. this.stopList = this.stopList.filter((item) => item != index);
  559. } else {
  560. if (videoElement) videoElement.pause();
  561. this.stopList.push(index);
  562. }
  563. },
  564. play(index) {
  565. let videoElement = document.getElementById('video' + index);
  566. if (videoElement) videoElement.play();
  567. this.stopList = this.stopList.filter((item) => item != index);
  568. },
  569. async getCameraList(list) {
  570. this.monitorData = list;
  571. list.forEach((item) => {
  572. this.codeList.push(item.deviceCode);
  573. });
  574. // this.getClickId(list[0]);
  575. },
  576. async getClickId(device) {
  577. this.camera = device;
  578. this.deviceCode = device.deviceCode;
  579. await this.getCameraUrl();
  580. let index = Math.floor(
  581. this.videoList.findIndex(
  582. (item) => item.cameraCode == device.deviceCode
  583. ) /
  584. (this.layout * this.layout)
  585. );
  586. this.$refs.carouselRef && this.$refs.carouselRef.setActiveItem(index);
  587. this.carouselIndex = index;
  588. },
  589. async getPreset() {
  590. const res = await realTime.getPreset(this.deviceCode);
  591. this.PresetList = res;
  592. },
  593. async getCameraUrl() {
  594. await realTime.delStreamProxy(this.deviceCode);
  595. const res = await realTime.getCameraUrl([this.deviceCode]);
  596. this.videoList = res;
  597. console.log(this.videoList);
  598. }
  599. }
  600. };
  601. </script>
  602. <style lang="scss" scoped>
  603. .inspection {
  604. display: flex;
  605. width: 100%;
  606. .left {
  607. padding-right: 0;
  608. height: 100%;
  609. width: 232px;
  610. }
  611. .center {
  612. width: calc(100%);
  613. padding-left: 10px;
  614. padding-right: 10px;
  615. padding-bottom: 20px;
  616. }
  617. }
  618. .missonList,
  619. .missonList * {
  620. box-sizing: border-box;
  621. }
  622. .missonList {
  623. background: #fff;
  624. padding: 10px;
  625. display: flex;
  626. flex-direction: column;
  627. gap: 4px;
  628. align-items: flex-start;
  629. justify-content: flex-start;
  630. align-self: stretch;
  631. flex-shrink: 0;
  632. position: relative;
  633. width: 232px;
  634. .list {
  635. width: 100%;
  636. ::v-deep .el-scrollbar__thumb {
  637. display: none;
  638. }
  639. }
  640. .title {
  641. background: #f2f4f5;
  642. display: flex;
  643. flex-direction: row;
  644. gap: 1px;
  645. align-items: center;
  646. justify-content: center;
  647. align-self: stretch;
  648. flex-shrink: 0;
  649. height: 24px;
  650. position: relative;
  651. > div {
  652. color: #404446;
  653. text-align: left;
  654. font-family: 'Alibaba PuHuiTi 2.0', sans-serif;
  655. font-size: 14px;
  656. line-height: 16px;
  657. font-weight: 400;
  658. position: relative;
  659. }
  660. }
  661. .row {
  662. padding: 4px 0px 4px 0px;
  663. display: flex;
  664. flex-direction: row;
  665. align-items: center;
  666. justify-content: space-between;
  667. align-self: stretch;
  668. flex-shrink: 0;
  669. position: relative;
  670. &:hover {
  671. background: linear-gradient(
  672. 270deg,
  673. rgba(44, 138, 224, 0.44) 0%,
  674. rgba(44, 138, 224, 0.22) 119.59%
  675. );
  676. }
  677. }
  678. .name {
  679. color: rgb(64, 68, 70);
  680. text-align: left;
  681. font-family: var(
  682. --small-none-regular-font-family,
  683. 'Alibaba PuHuiTi 2.0',
  684. sans-serif
  685. );
  686. font-size: var(--small-none-regular-font-size, 14px);
  687. line-height: var(--small-none-regular-line-height, 16px);
  688. font-weight: var(--small-none-regular-font-weight, 400);
  689. position: relative;
  690. }
  691. .done {
  692. color: #32a2d4;
  693. text-align: left;
  694. font-family: var(
  695. --small-none-regular-font-family,
  696. 'Alibaba PuHuiTi 2.0',
  697. sans-serif
  698. );
  699. font-size: var(--small-none-regular-font-size, 14px);
  700. line-height: var(--small-none-regular-line-height, 16px);
  701. font-weight: var(--small-none-regular-font-weight, 400);
  702. position: relative;
  703. }
  704. .doing {
  705. color: #ffb323;
  706. text-align: left;
  707. font-family: var(
  708. --small-none-regular-font-family,
  709. 'Alibaba PuHuiTi 2.0',
  710. sans-serif
  711. );
  712. font-size: var(--small-none-regular-font-size, 14px);
  713. line-height: var(--small-none-regular-line-height, 16px);
  714. font-weight: var(--small-none-regular-font-weight, 400);
  715. position: relative;
  716. }
  717. .todo {
  718. color: #ff4d4f;
  719. text-align: left;
  720. font-family: var(
  721. --small-none-regular-font-family,
  722. 'Alibaba PuHuiTi 2.0',
  723. sans-serif
  724. );
  725. font-size: var(--small-none-regular-font-size, 14px);
  726. line-height: var(--small-none-regular-line-height, 16px);
  727. font-weight: var(--small-none-regular-font-weight, 400);
  728. position: relative;
  729. }
  730. }
  731. .tree {
  732. background-color: #fff;
  733. margin-top: 16px;
  734. }
  735. .el-carousel {
  736. ::v-deep .el-carousel__container {
  737. height: calc(100% - 27px);
  738. }
  739. }
  740. .page {
  741. display: flex;
  742. align-content: space-between;
  743. flex-wrap: wrap;
  744. gap: 5px;
  745. height: 100%;
  746. .videoItem {
  747. border: 4px solid transparent;
  748. position: relative;
  749. .mask1 {
  750. position: absolute;
  751. top: 0;
  752. left: 0;
  753. width: 50px;
  754. height: 20px;
  755. z-index: 111;
  756. }
  757. .mask2 {
  758. position: absolute;
  759. top: 50%;
  760. left: 50%;
  761. transform: translate(-50%, -50%);
  762. width: 50px;
  763. height: 50px;
  764. z-index: 111;
  765. background-color: #000000d3;
  766. border-radius: 50%;
  767. display: flex;
  768. justify-content: center;
  769. align-items: center;
  770. .play {
  771. width: 70%;
  772. transform: translateX(3px);
  773. }
  774. }
  775. }
  776. .active {
  777. border: 4px solid #2c8ae0;
  778. }
  779. img {
  780. vertical-align: middle;
  781. }
  782. }
  783. .deviceInfo,
  784. .deviceInfo * {
  785. box-sizing: border-box;
  786. }
  787. .deviceInfo {
  788. background: #fff;
  789. padding: 10px;
  790. display: flex;
  791. flex-direction: column;
  792. gap: 4px;
  793. align-items: flex-start;
  794. justify-content: flex-start;
  795. align-self: stretch;
  796. flex-shrink: 0;
  797. position: relative;
  798. width: 232px;
  799. .frame-48095487 {
  800. background: #f2f4f5;
  801. display: flex;
  802. flex-direction: row;
  803. gap: 1px;
  804. align-items: center;
  805. justify-content: center;
  806. align-self: stretch;
  807. flex-shrink: 0;
  808. height: 24px;
  809. position: relative;
  810. }
  811. .div {
  812. color: rgb(64, 68, 70);
  813. text-align: left;
  814. font-family: 'Alibaba PuHuiTi 2.0', sans-serif;
  815. font-size: 14px;
  816. line-height: 16px;
  817. font-weight: 400;
  818. position: relative;
  819. }
  820. .row {
  821. padding: 4px 0px 4px 0px;
  822. display: flex;
  823. flex-direction: row;
  824. align-items: center;
  825. justify-content: space-between;
  826. align-self: stretch;
  827. flex-shrink: 0;
  828. position: relative;
  829. }
  830. .name {
  831. color: #32a2d4;
  832. text-align: left;
  833. font-family: 'Alibaba PuHuiTi 2.0', sans-serif;
  834. font-size: 14px;
  835. line-height: 16px;
  836. font-weight: 400;
  837. position: relative;
  838. }
  839. }
  840. .handle {
  841. display: flex;
  842. padding: 10px;
  843. flex-direction: column;
  844. align-items: flex-start;
  845. gap: 16px;
  846. flex: 1 0 0;
  847. background: #fff;
  848. margin-top: 10px;
  849. }
  850. .slider {
  851. display: flex;
  852. justify-content: space-between;
  853. align-items: center;
  854. align-self: stretch;
  855. padding-left: 10px;
  856. .sliderNum {
  857. display: flex;
  858. height: 17px;
  859. padding: 10px;
  860. flex-direction: column;
  861. justify-content: center;
  862. align-items: center;
  863. gap: 10px;
  864. border: 1px solid #cdcfd0;
  865. width: 29px;
  866. box-sizing: border-box;
  867. ::v-deep .el-slider__button {
  868. background-color: #fff;
  869. border-color: #ff7b30;
  870. }
  871. }
  872. }
  873. .moreHandle {
  874. display: flex;
  875. width: 200px;
  876. padding: 5px 0px;
  877. flex-direction: column;
  878. justify-content: center;
  879. align-items: center;
  880. gap: 4px;
  881. position: relative;
  882. border-radius: 4px;
  883. border: 2px solid #e3e5e6;
  884. .row {
  885. display: flex;
  886. align-items: flex-start;
  887. align-self: stretch;
  888. }
  889. .line {
  890. width: 180px;
  891. height: 1px;
  892. background: #e3e5e6;
  893. position: absolute;
  894. top: 50%;
  895. left: 50%;
  896. transform: translate(-50%, -50%);
  897. }
  898. .item {
  899. display: flex;
  900. height: 21px;
  901. padding: 0px 9px;
  902. justify-content: center;
  903. align-items: center;
  904. width: 39px;
  905. cursor: not-allowed;
  906. border-left: 1px solid #e3e5e6;
  907. border-right: 1px solid #e3e5e6;
  908. &:first-child {
  909. border-left: 0;
  910. }
  911. &:last-child {
  912. border-right: 0;
  913. }
  914. }
  915. .normal {
  916. cursor: pointer;
  917. }
  918. }
  919. .center-handle {
  920. display: flex;
  921. height: 42px;
  922. justify-content: space-between;
  923. align-items: center;
  924. align-self: stretch;
  925. width: 100%;
  926. .layout-type {
  927. display: flex;
  928. width: 98px;
  929. align-items: center;
  930. position: relative;
  931. > div {
  932. display: flex;
  933. }
  934. }
  935. .play {
  936. display: flex;
  937. align-items: flex-start;
  938. gap: 24px;
  939. }
  940. .video-handle {
  941. display: flex;
  942. align-items: flex-end;
  943. gap: 16px;
  944. }
  945. }
  946. .monitor {
  947. height: 100%;
  948. padding: 10px;
  949. }
  950. .layout {
  951. width: 20px;
  952. height: 15px;
  953. padding: 1px;
  954. display: flex;
  955. flex-wrap: wrap;
  956. gap: 1px;
  957. border: 1px #404446 solid;
  958. }
  959. .group {
  960. display: flex;
  961. padding: 4px;
  962. align-items: flex-start;
  963. gap: 4px;
  964. position: absolute;
  965. top: 20px;
  966. border-radius: 4px;
  967. border: 0.5px solid #404446;
  968. background: #fff;
  969. }
  970. </style>