VideoMonitorEdit.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. <template>
  2. <Dialog custom-show type="xl" title="视频监控" class="dialog" hide-footer draggable @close="reset">
  3. <div class="search-box">
  4. <div class="box-left">
  5. <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="70px" label-position="left">
  6. <el-form-item prop="name">
  7. <el-input v-model="queryParams.name" class="custom-input2" placeholder="请输入摄像头名称" style="width: 500px" />
  8. </el-form-item>
  9. <el-form-item label="实景视频" prop="dict_value">
  10. <el-select
  11. v-model="queryParams.dict_value"
  12. class="custom-select"
  13. popper-class="custom-select-popper"
  14. :teleported="false"
  15. >
  16. <el-option v-for="item in video_type" :key="item.value" :label="item.label" :value="item.value" />
  17. </el-select>
  18. </el-form-item>
  19. <el-form-item>
  20. <div class="common-btn-primary" @click="handleQuery">搜索</div>
  21. <div class="common-btn" @click="resetQuery">重置</div>
  22. </el-form-item>
  23. </el-form>
  24. </div>
  25. <div v-show="!editVideo" class="common-btn-primary2 edit-icon" style="margin-top: -20px" @click="activeEdit">编辑首页视频</div>
  26. <div v-show="editVideo" class="edit-box">
  27. <div class="flex">
  28. <div v-for="(item, index) in editData" :key="index" class="box-item">
  29. <div class="edit-img" :title="item.name">
  30. <span class="edit-title">{{ item.name }}</span>
  31. <div class="close-btn" @click="deleteItem(index)"></div>
  32. </div>
  33. </div>
  34. </div>
  35. <div class="flex" style="flex-direction: column; align-items: center">
  36. <div class="common-btn-primary3" @click="handleSave">保存</div>
  37. <div class="common-btn-danger2" @click="handleCancel">取消</div>
  38. </div>
  39. </div>
  40. </div>
  41. <div class="border"></div>
  42. <div class="video-list2">
  43. <div v-for="(item, index) in dialogListData" :key="index" class="video-box" @click="selectItem(item)">
  44. <div class="video-label">
  45. <span class="label">{{ item.name }}</span>
  46. </div>
  47. <div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
  48. <div v-if="editVideo">
  49. <div v-if="item.sort" class="active-tag"></div>
  50. <div :class="item.sort ? 'common-checked-active' : 'common-checked'"></div>
  51. <div class="img"></div>
  52. </div>
  53. <HKVideo v-else :dot_data="item" autoplay />
  54. </div>
  55. </div>
  56. </div>
  57. <div class="footer">
  58. <pagination
  59. v-show="total > queryParams.size"
  60. v-model:page="queryParams.current"
  61. v-model:limit="queryParams.size"
  62. :total="total"
  63. layout="total, prev, pager, next"
  64. @pagination="getList"
  65. />
  66. <div v-if="total === 0" style="width: 100%; text-align: center; font-size: 18px; font-weight: bold">暂无数据</div>
  67. </div>
  68. <div id="container" style="display: none"></div>
  69. </Dialog>
  70. <div v-if="showTip" class="danger-tip" :style="{ zIndex: zIndex }">首页视频数量已达6个上限,如需继续操作请先取消已选择视频。</div>
  71. </template>
  72. <script lang="ts" setup>
  73. import { getEmergencyVideoCata, getUserVideoPoints, getVideoList, updateUserVideoPoints } from '@/api/videoMonitor';
  74. import { deepClone } from '@/utils';
  75. import useAppStore from '@/store/modules/app';
  76. import useMapStore from '@/store/modules/map';
  77. interface LngLat {
  78. longitude: number;
  79. latitude: number;
  80. }
  81. const props = defineProps({
  82. modelValue: {
  83. type: Boolean,
  84. default: () => {
  85. return false;
  86. }
  87. },
  88. lngLat: {
  89. type: Object as () => LngLat
  90. }
  91. });
  92. const mapStore = useMapStore();
  93. const emits = defineEmits(['update:modelValue']);
  94. const proxy = getCurrentInstance()?.proxy;
  95. const { video_type } = toRefs<any>(proxy?.useDict('video_type'));
  96. //查看更多数据
  97. const queryFormRef = ref();
  98. const queryParams = reactive({
  99. current: 1,
  100. size: 8,
  101. dict_value: '',
  102. name: ''
  103. });
  104. let total = ref(0);
  105. let editVideo = ref(false);
  106. // 选中的视频
  107. let editData = ref([]);
  108. let dialogListData = ref([]);
  109. let showTip = ref(false);
  110. const appStore = useAppStore();
  111. let zIndex = ref(999);
  112. watch(
  113. showTip,
  114. () => {
  115. if (showTip.value) {
  116. zIndex.value = appStore.getZIndex();
  117. }
  118. },
  119. { immediate: true }
  120. );
  121. const getList = () => {
  122. let newParams = {
  123. latitude: props.lngLat.latitude,
  124. longitude: props.lngLat.longitude,
  125. current: queryParams.current,
  126. size: queryParams.size,
  127. query: {
  128. name: queryParams.name
  129. }
  130. };
  131. if (!!queryParams.dict_value) {
  132. newParams.query.dict_value = queryParams.dict_value;
  133. }
  134. getEmergencyVideoCata(newParams).then((res) => {
  135. dialogListData.value = res.rows;
  136. total.value = res.total;
  137. if (editVideo.value && editData.value) {
  138. filterData(editData.value);
  139. }
  140. });
  141. };
  142. const getVideoInfoList = () => {
  143. getVideoList(queryParams).then((res) => {
  144. mapStore.setTrackState(res.data);
  145. });
  146. };
  147. const selectItem = (item) => {
  148. if (editVideo.value) {
  149. if (editData.value.length >= 6) {
  150. showTip.value = true;
  151. setTimeout(() => {
  152. showTip.value = false;
  153. }, 2500);
  154. } else {
  155. editData.value.push(item);
  156. }
  157. }
  158. };
  159. const deleteItem = (index) => {
  160. editData.value.splice(index, 1);
  161. };
  162. /** 表单重置 */
  163. const reset = () => {
  164. queryParams.current = 1;
  165. queryParams.dict_value = '';
  166. queryParams.name = '';
  167. emits('update:modelValue', false);
  168. };
  169. /** 搜索按钮操作 */
  170. const handleQuery = () => {
  171. queryParams.current = 1;
  172. getList();
  173. // getVideoInfoList();
  174. };
  175. /** 重置按钮操作 */
  176. const resetQuery = () => {
  177. queryFormRef.value?.resetFields();
  178. handleQuery();
  179. };
  180. // 开启编辑视频
  181. const activeEdit = () => {
  182. getUserVideoPoints().then((res) => {
  183. filterData(res.data.videoInfos);
  184. editData.value = deepClone(res.data.videoInfos);
  185. editVideo.value = true;
  186. });
  187. };
  188. const filterData = (data) => {
  189. data.forEach((item) => {
  190. for (let i = 0; i < dialogListData.value.length; i++) {
  191. if (item.video_code_int === dialogListData.value[i].video_code) {
  192. dialogListData.value[i].sort = true;
  193. break;
  194. }
  195. }
  196. });
  197. };
  198. // 关闭编辑
  199. const handleCancel = () => {
  200. editVideo.value = false;
  201. };
  202. // 保存编辑
  203. const handleSave = () => {
  204. const data = [];
  205. editData.value.forEach((item) => {
  206. data.push(item.video_code_int);
  207. });
  208. updateUserVideoPoints(data).then(() => {
  209. getList();
  210. handleCancel();
  211. });
  212. };
  213. onMounted(() => {
  214. getList();
  215. // getVideoInfoList();
  216. });
  217. </script>
  218. <style lang="scss" scoped>
  219. .search-box {
  220. display: flex;
  221. width: 100%;
  222. justify-content: space-between;
  223. align-items: center;
  224. .el-form--inline .el-form-item {
  225. margin-right: 15px;
  226. }
  227. }
  228. .video-list2 {
  229. display: flex;
  230. flex-wrap: wrap;
  231. padding: 0 10px;
  232. .video-box {
  233. width: 288px;
  234. height: 200px;
  235. margin-right: 15px;
  236. cursor: pointer;
  237. cursor: pointer;
  238. background: url('@/assets/images/video/videoBg.png') no-repeat;
  239. background-size: 100% 100%;
  240. padding: 9.5px 3.8px 9px 5.5px;
  241. position: relative;
  242. margin-bottom: 15px;
  243. position: relative;
  244. display: flex;
  245. flex-direction: column;
  246. align-items: center;
  247. &:nth-child(4),
  248. &:nth-child(8) {
  249. margin-right: 0;
  250. }
  251. .video-label {
  252. position: absolute;
  253. bottom: 8px;
  254. right: 4px;
  255. z-index: 901;
  256. display: flex;
  257. .label {
  258. width: 186px;
  259. height: 24px;
  260. padding-right: 5px;
  261. line-height: 24px;
  262. font-size: 14px;
  263. white-space: nowrap;
  264. overflow: hidden;
  265. text-overflow: ellipsis;
  266. padding-left: 10px;
  267. color: #fff;
  268. background-color: rgba(0, 0, 0, 0.4);
  269. text-align: right;
  270. }
  271. &::before {
  272. content: '';
  273. width: 0;
  274. height: 0;
  275. border-bottom: 24px solid rgba(0, 0, 0, 0.4);
  276. border-left: 24px solid transparent;
  277. }
  278. }
  279. }
  280. }
  281. .img {
  282. width: 278.5px;
  283. height: 183px;
  284. margin-left: 1px;
  285. background-color: #000;
  286. }
  287. .active-tag {
  288. position: absolute;
  289. top: 13px;
  290. left: 10px;
  291. width: 83px;
  292. height: 25px;
  293. background: url('@/assets/images/video/indexTag.png') no-repeat;
  294. background-size: 100% 100%;
  295. }
  296. .edit-box {
  297. display: flex;
  298. justify-content: space-between;
  299. align-items: center;
  300. border-radius: 8px;
  301. padding: 3px 5px;
  302. width: 545px;
  303. height: 83px;
  304. background: url('@/assets/images/video/editBg.png') no-repeat;
  305. background-size: 100% 100%;
  306. position: absolute;
  307. right: 20px;
  308. top: 27px;
  309. }
  310. .box-item {
  311. position: relative;
  312. margin-left: 8px;
  313. &:first-child {
  314. margin-left: 0;
  315. }
  316. .edit-img {
  317. width: 65px;
  318. height: 65px;
  319. background-color: #000;
  320. }
  321. .edit-title {
  322. color: #fff;
  323. display: -webkit-box;
  324. -webkit-box-orient: vertical;
  325. -webkit-line-clamp: 3; /* 设置显示的行数 */
  326. overflow: hidden;
  327. text-overflow: ellipsis;
  328. }
  329. .close-btn {
  330. position: absolute;
  331. top: 0;
  332. right: 0;
  333. cursor: pointer;
  334. width: 15px;
  335. height: 15px;
  336. background: url('@/assets/images/video/close.png') no-repeat;
  337. background-size: 100% 100%;
  338. z-index: 1;
  339. }
  340. }
  341. .footer {
  342. height: 30px;
  343. display: flex;
  344. justify-content: flex-end;
  345. margin-bottom: 30px;
  346. .pagination-container {
  347. margin: 0;
  348. }
  349. :deep(.el-pagination__total) {
  350. color: #a7ccdf !important;
  351. }
  352. :deep(.el-pagination) {
  353. .btn-next,
  354. .btn-prev {
  355. background-color: transparent !important;
  356. border: none !important;
  357. .el-icon {
  358. color: #a7ccdf !important;
  359. }
  360. }
  361. .btn-prev:disabled,
  362. .btn-next:disabled {
  363. background-color: transparent !important;
  364. border: none !important;
  365. }
  366. .el-pager li {
  367. text-align: center;
  368. color: #a7ccdf !important;
  369. background-color: #0e3064 !important;
  370. border: 1px solid #0c57a7 !important;
  371. &:hover {
  372. background-color: #038dff !important;
  373. border: 1px solid #038dff !important;
  374. }
  375. }
  376. .el-pager li.is-active {
  377. background-color: #038dff !important;
  378. border: 1px solid #038dff !important;
  379. }
  380. }
  381. }
  382. .flex {
  383. display: flex;
  384. align-items: center;
  385. }
  386. .border {
  387. background-color: #15428d;
  388. width: 100%;
  389. height: 1px;
  390. margin-bottom: 30px;
  391. }
  392. .edit-icon {
  393. display: flex;
  394. align-items: center;
  395. &::before {
  396. content: '';
  397. display: inline-block;
  398. width: 18px;
  399. height: 16px;
  400. background: url('@/assets/images/video/setting.png') no-repeat;
  401. background-size: 100% 100%;
  402. margin-right: 10px;
  403. }
  404. }
  405. .common-checked,
  406. .common-checked-active {
  407. position: absolute;
  408. top: 13px;
  409. right: 12px;
  410. z-index: 9;
  411. }
  412. :deep(.el-form) {
  413. .el-form-item__label {
  414. color: #ffffff !important;
  415. }
  416. }
  417. //.dialog {
  418. // :deep(.dialog-header) {
  419. // min-height: 150px;
  420. // }
  421. //}
  422. .common-btn-primary {
  423. width: 94px;
  424. height: 60px;
  425. }
  426. .common-btn {
  427. width: 66px;
  428. height: 32px;
  429. }
  430. </style>