|
|
@@ -0,0 +1,388 @@
|
|
|
+<template>
|
|
|
+ <div class="cameraGroup">
|
|
|
+ <el-collapse-item :name="cameraGroup.groupName" @keydown.space.stop.prevent @keydown.enter.stop.prevent>
|
|
|
+ <template #title>
|
|
|
+ <div
|
|
|
+ class="cameraGroupTitle"
|
|
|
+ :class="playingGroup?.id === props.cameraGroup.id ? 'playingCameraGroup' : ''"
|
|
|
+ @click.stop=""
|
|
|
+ @dblclick="handleRenameGroup"
|
|
|
+ >
|
|
|
+ <div class="renameGroupInput" v-show="showRenameGroupInput">
|
|
|
+ <img class="folderIcon" src="@/assets/icons/nine-square-grid/folder-white.png" />
|
|
|
+ <el-input
|
|
|
+ v-model="inputNewGroupName"
|
|
|
+ class="GroupNameInput"
|
|
|
+ placeholder="为此区域命名"
|
|
|
+ maxlength="15"
|
|
|
+ show-word-limit
|
|
|
+ ref="groupNameInputRef"
|
|
|
+ @blur="enterNewName"
|
|
|
+ @keyup.enter="$event.target.blur()"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="IconAndGroupName" v-show="!showRenameGroupInput">
|
|
|
+ <img class="folderImg" src="@/assets/icons/nine-square-grid/folder.png" alt="" />
|
|
|
+ <div class="groupName" :title="cameraGroup.groupName">
|
|
|
+ {{ cameraGroup.groupName }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="groupOperationBar">
|
|
|
+ <img
|
|
|
+ src="@/assets/icons/nine-square-grid/more.png"
|
|
|
+ class="groupOperationIcon"
|
|
|
+ @click="showGroupOperation = !showGroupOperation"
|
|
|
+ @dblclick.stop=""
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="groupOperation" v-show="showGroupOperation">
|
|
|
+ <div @click="handelStartPlay()" class="groupOperationItem">
|
|
|
+ {{ cameraGroup.id !== playingGroup?.id ? '开始播放' : '停止播放' }}
|
|
|
+ </div>
|
|
|
+ <div @click="handleDelete(cameraGroup)" class="groupOperationItem"> 删除区域 </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div class="addCamera" @click.stop="addCamera">
|
|
|
+ <div class="addCameraIcon">
|
|
|
+ <img src="@/assets/icons/nine-square-grid/add.png" />
|
|
|
+ </div>
|
|
|
+ <div>添加点位</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <CameraListOfGroup :cameraGroup="cameraGroup" />
|
|
|
+ </el-collapse-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <el-dialog v-model="showCameraTreeDialog" width="500" :title="`添加相机至“${cameraGroup.groupName}”区域`">
|
|
|
+ <CameraTreeOfGroupList :cameraGroup="cameraGroup" />
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+ import { storeToRefs } from 'pinia';
|
|
|
+ import { ref, watch, nextTick } from 'vue';
|
|
|
+ import CameraTreeOfGroupList from './CameraTreeOfGroupList.vue';
|
|
|
+ import { ElCollapseItem, ElDialog, ElMessageBox, ElInput, ElMessage } from 'element-plus';
|
|
|
+ import { useCameraGroupList } from '@/store/modules/useCameraGroupList';
|
|
|
+ import { userGridType } from '@/store/modules/userGridType';
|
|
|
+ import { GridType } from '@/views/disaster/monitor/splitScreenRetrieval/type';
|
|
|
+ import type { CameraGroupType } from '@/views/disaster/monitor/splitScreenRetrieval/type';
|
|
|
+ import { modifyCameraGroupApi } from '@/api/nine-square-grid';
|
|
|
+ import CameraListOfGroup from './CameraListOfGroup.vue';
|
|
|
+
|
|
|
+ const showGroupOperation = ref(false);
|
|
|
+ const showCameraTreeDialog = ref(false);
|
|
|
+ const props = defineProps<{
|
|
|
+ cameraGroup: CameraGroupType;
|
|
|
+ activeGroup: string[];
|
|
|
+ }>();
|
|
|
+
|
|
|
+ const showRenameGroupInput = ref(false);
|
|
|
+ let groupOriginName = props.cameraGroup.groupName;
|
|
|
+ const inputNewGroupName = ref('');
|
|
|
+ const groupNameInputRef = ref();
|
|
|
+
|
|
|
+ const { cameraGroupList, playingGroup, isPlaying, isPaused, playIntervalTime } = storeToRefs(useCameraGroupList());
|
|
|
+ const { deleteCameraGroup, groupStartPlay, setPlayGroup, stopPlay } = useCameraGroupList();
|
|
|
+ const { changeGridType } = userGridType();
|
|
|
+
|
|
|
+ // 控制播放/删除菜单的隐藏
|
|
|
+ const closeGroupOperation = (event) => {
|
|
|
+ if (event.target.className !== 'groupOperationItem') showGroupOperation.value = false;
|
|
|
+ if (event.target.innerText === '开始播放') {
|
|
|
+ handelStartPlay();
|
|
|
+ showGroupOperation.value = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ function handleRenameGroup() {
|
|
|
+ showRenameGroupInput.value = true;
|
|
|
+ nextTick(() => {
|
|
|
+ groupNameInputRef.value.focus();
|
|
|
+ inputNewGroupName.value = groupOriginName;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function enterNewName() {
|
|
|
+ if (inputNewGroupName.value === '') {
|
|
|
+ showRenameGroupInput.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const camera = cameraGroupList.value.find((x) => x.groupName === inputNewGroupName.value);
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (camera && camera.id === props.cameraGroup.id) return;
|
|
|
+ else if (camera && camera.id !== props.cameraGroup.id)
|
|
|
+ return ElMessage({ message: '已存在同名区域', type: 'error' });
|
|
|
+ } finally {
|
|
|
+ showRenameGroupInput.value = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ props.cameraGroup.groupName = inputNewGroupName.value;
|
|
|
+ groupOriginName = inputNewGroupName.value;
|
|
|
+ showRenameGroupInput.value = false;
|
|
|
+ modifyCameraGroupApi({
|
|
|
+ groupId: props.cameraGroup.id,
|
|
|
+ groupName: inputNewGroupName.value,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function handelStartPlay() {
|
|
|
+ // 如果点击的是其他区域的轮播按钮
|
|
|
+ const changeGroup = props.cameraGroup.id !== playingGroup.value?.id;
|
|
|
+ if (isPlaying.value) {
|
|
|
+ ElMessageBox.confirm(changeGroup ? '是否切换播放区域' : '是否取消当前区域相机播放', '提示', {
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ customClass: 'customMessageBox--warning',
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ if (changeGroup) {
|
|
|
+ isPlaying.value = false;
|
|
|
+ stopPlay(playingGroup.value?.id!);
|
|
|
+ playClickedGroup();
|
|
|
+ } else {
|
|
|
+ stopPlay(props.cameraGroup.id, true);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ return;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ playClickedGroup();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function playClickedGroup() {
|
|
|
+ isPlaying.value = true;
|
|
|
+ setPlayGroup(props.cameraGroup);
|
|
|
+ playIntervalTime.value = props.cameraGroup.playIntervalSec ? props.cameraGroup.playIntervalSec : 60;
|
|
|
+ isPaused.value = Boolean(props.cameraGroup.isPaused);
|
|
|
+ changeGridType(GridType.nineGrids);
|
|
|
+ groupStartPlay(playIntervalTime.value);
|
|
|
+ modifyCameraGroupApi({
|
|
|
+ groupId: props.cameraGroup.id,
|
|
|
+ isDefault: 1,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function addCamera() {
|
|
|
+ showCameraTreeDialog.value = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleDelete(cameraGroup: CameraGroupType) {
|
|
|
+ const text = '删除后,区域数据不可恢复,需要重新添加,是否确认删除该区域?';
|
|
|
+ ElMessageBox.confirm(text, '提示', {
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ customClass: 'customMessageBox--warning',
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ deleteCameraGroup(cameraGroup.id);
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ return;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => showGroupOperation.value,
|
|
|
+ (newValue) => {
|
|
|
+ newValue
|
|
|
+ ? document.addEventListener('mousedown', closeGroupOperation)
|
|
|
+ : document.removeEventListener('mousedown', closeGroupOperation);
|
|
|
+ },
|
|
|
+ );
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .cameraGroup {
|
|
|
+ margin-bottom: 1px;
|
|
|
+ .cameraGroupTitle {
|
|
|
+ height: 38px;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ color: #333333;
|
|
|
+ border-radius: 4px;
|
|
|
+ position: relative;
|
|
|
+ cursor: default;
|
|
|
+ .arrowIcon {
|
|
|
+ height: 16px;
|
|
|
+ width: 16px;
|
|
|
+ margin-right: 12px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .renameGroupInput {
|
|
|
+ height: 32px;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background-color: #1777ff;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 24px;
|
|
|
+ padding-right: 6px;
|
|
|
+
|
|
|
+ .folderIcon {
|
|
|
+ height: 24px;
|
|
|
+ margin-left: 12px;
|
|
|
+ margin-right: 12px;
|
|
|
+ }
|
|
|
+ .GroupNameInput {
|
|
|
+ height: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .IconAndGroupName {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .folderImg {
|
|
|
+ height: 24px;
|
|
|
+ width: 24px;
|
|
|
+ margin-right: 12px;
|
|
|
+ }
|
|
|
+ .groupName {
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .groupOperationBar {
|
|
|
+ visibility: hidden;
|
|
|
+ margin-left: 10px;
|
|
|
+ margin-right: 10px;
|
|
|
+ .groupOperationIcon {
|
|
|
+ height: 20px;
|
|
|
+ width: 20px;
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover .groupOperationBar {
|
|
|
+ visibility: visible;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .groupOperation {
|
|
|
+ display: block;
|
|
|
+ height: 63px;
|
|
|
+ width: 130px;
|
|
|
+ position: absolute;
|
|
|
+ bottom: -63px;
|
|
|
+ right: 5px;
|
|
|
+ box-shadow: 0px 0px 10px 2px rgb(0, 0, 0, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ background: #f4f7ff;
|
|
|
+ outline: 1px solid rgba(245, 248, 255, 0.25);
|
|
|
+ z-index: 999;
|
|
|
+ .groupOperationItem {
|
|
|
+ height: 31.5px;
|
|
|
+ line-height: 31.5px;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ color: #fff;
|
|
|
+ background-color: #1777ff;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .playingCameraGroup {
|
|
|
+ height: 38px;
|
|
|
+ background-color: #1777ff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cameraGroupTitle:not(.playingCameraGroup):hover {
|
|
|
+ border-radius: 4px;
|
|
|
+ background-color: #c0c4d2;
|
|
|
+ }
|
|
|
+
|
|
|
+ .addCamera {
|
|
|
+ height: 32px;
|
|
|
+ width: fit-content;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-left: 74px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 32px;
|
|
|
+ color: #333333;
|
|
|
+ text-align: left;
|
|
|
+ white-space: nowrap;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ .addCameraIcon {
|
|
|
+ margin-right: 14px;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ img {
|
|
|
+ height: 20px;
|
|
|
+ width: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ content: '+';
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ top: -7px;
|
|
|
+ font-size: 20px;
|
|
|
+ color: #1777ff;
|
|
|
+ text-align: center;
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-collapse-item__header) {
|
|
|
+ height: 38px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-collapse-item__header:has(.playingCameraGroup)) {
|
|
|
+ height: 38px;
|
|
|
+ background-color: #1777ff;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ .groupName,
|
|
|
+ svg {
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ .IconAndGroupName img {
|
|
|
+ content: url('@/assets/icons/nine-square-grid/folder-white.png');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-collapse-item__header:not(.el-collapse-item__header:has(.playingCameraGroup)):hover) {
|
|
|
+ background-color: #cdd8ff;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-collapse-item__header:not(.el-collapse-item__header:has(.playingCameraGroup)):hover .cameraGroupTitle) {
|
|
|
+ background-color: #cdd8ff;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-dialog__header) {
|
|
|
+ text-align: left;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-dialog__body) {
|
|
|
+ }
|
|
|
+</style>
|