CameraViewSetting.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <template>
  2. <div style="position: relative">
  3. <div class="toolbarWrapper">
  4. <!-- <ViewWindowSetting v-model="viewType" @update:model-value="handleUpdateViewType" /> -->
  5. <!-- <el-tooltip content="全屏">
  6. <el-icon class="el-input__icon" :size="18" style="margin-left: 10px; margin-right: 10px">
  7. <FullscreenExitOutlined role="full" @click="enterFullscreen" />
  8. </el-icon>
  9. </el-tooltip> -->
  10. <RenderSwitch />
  11. <FenceAppSetting />
  12. </div>
  13. <div
  14. class="cameraViewSettingWrapper"
  15. :style="{ width: domWidth + 'px', height: domHeight + 'px' }"
  16. >
  17. <div class="fenceEditorWrapper" v-if="cameraAlgoStore.selectedAlgoDetail.electronicFenceBool">
  18. <FenceEditor
  19. ref="fenceEditorRef"
  20. :dom-width="domWidth"
  21. :canvas-size="{ width: canvasWidth, height: canvasHeight }"
  22. :line-points="fenceStore.serverFencePoints || []"
  23. />
  24. </div>
  25. <div class="cameraVideo">
  26. <CameraLiveVideo />
  27. </div>
  28. </div>
  29. <div
  30. class="presetAddWrapper"
  31. :class="{ hidePresetControlCls: isEdit }"
  32. v-if="!!cameraDetailStore.detail?.isPtz"
  33. >
  34. <CameraViewScale />
  35. <CameraDirectionControl />
  36. <ElButton
  37. type="primary"
  38. @click="handleAddPreset"
  39. size="small"
  40. style="margin-top: 20px; width: 100px"
  41. >添加预置位</ElButton
  42. >
  43. <AddPresetModal v-if="addPresetModalVisible" @close="handleClose" @ok="handleAddPresetOk" />
  44. </div>
  45. </div>
  46. <div class="presetWrapper">
  47. <PresetSelect />
  48. <FenceToolbar
  49. :style="{ display: drawable ? 'flex' : 'none' }"
  50. @remove="handleRemove"
  51. @save="handleSave"
  52. @toggle-editable="toggleEditable"
  53. @toggle-range="toggleRange"
  54. :is-edit="isEdit"
  55. />
  56. </div>
  57. <div class="cameraParamsSettingWrapper">
  58. <!-- <div class="cameraParamsSetting">
  59. <CameraParams />
  60. </div> -->
  61. <div class="algorithmsSetting"> <AlgorithmsSetting /> </div>
  62. </div>
  63. </template>
  64. <script lang="ts" setup>
  65. import { computed, ref, watchEffect } from 'vue';
  66. import FenceToolbar from '../FenceToolbar/FenceToolbar.vue';
  67. import FenceEditor from '../FenceEditorV2/FenceEditor.vue';
  68. import CameraLiveVideo from '../CameraLiveVideo/CameraLiveVideo.vue';
  69. import PresetSelect from '../PresetSelect/PresetSelect.vue';
  70. // import { ViewType } from '../ViewWindowSetting/types';
  71. import useFenceStore from '../../store/useFenceStore';
  72. import AddPresetModal from '../AddPresetModal/AddPresetModal.vue';
  73. import usePresetListStore from '../../store/usePresetListStore';
  74. import useCameraDetailStore from '../../store/useCameraDetailStore';
  75. import useCameraAlgoStore from '../../store/useCameraAlgoStore';
  76. import AlgorithmsSetting from '../AlgorithmsSetting/AlgorithmsSetting.vue';
  77. import RenderSwitch from '../RenderSwitch/RenderSwitch.vue';
  78. import { FullscreenExitOutlined } from '@vicons/antd';
  79. import FenceAppSetting from '../FenceAppSetting/FenceAppSetting.vue';
  80. import { ElMessage } from 'element-plus';
  81. import CameraDirectionControl from '../CameraDirectionControl/CameraDirectionControl.vue';
  82. import CameraViewScale from './CameraViewScale.vue';
  83. import { canvasHeight, canvasWidth, domHeight, domWidth } from './constants';
  84. import useFullscreen from 'vue-hooks-plus/lib/useFullscreen';
  85. import { updateCameraAlgoApi } from '@/api/camera/camera-preview';
  86. import { RegionJudge } from '../FenceToolbar/constants';
  87. const emits = defineEmits<{
  88. (e: 'changeTreeRender', render: number | string): unknown;
  89. }>();
  90. const [, { enterFullscreen }] = useFullscreen(() => document.querySelector('.cameraVideo'));
  91. const fenceEditorRef = ref<typeof FenceEditor | null>(null);
  92. const fenceStore = useFenceStore();
  93. const presetStore = usePresetListStore();
  94. const cameraDetailStore = useCameraDetailStore();
  95. const cameraAlgoStore = useCameraAlgoStore();
  96. const { getCameraAlgoList } = cameraAlgoStore;
  97. // const viewType = ref<ViewType>(ViewType.window1);
  98. const addPresetModalVisible = ref(false);
  99. const handleClose = () => {
  100. addPresetModalVisible.value = false;
  101. };
  102. const handleAddPresetOk = () => {
  103. presetStore.getPresetList(cameraDetailStore.cameraId);
  104. handleClose();
  105. };
  106. const handleRemove = () => {
  107. fenceEditorRef.value?.remove();
  108. };
  109. const isEdit = ref(false);
  110. /** 退出编辑模式 */
  111. const toggleEditable = (val: boolean) => {
  112. isEdit.value = val;
  113. if (val) {
  114. fenceEditorRef.value?.setEditMode();
  115. } else {
  116. fenceEditorRef.value?.exitEditMode();
  117. }
  118. };
  119. const toggleRange = () => {
  120. const selectedAlgoDetail = cameraAlgoStore.selectedAlgoDetail;
  121. const cameraId = cameraDetailStore.cameraId;
  122. const extraStr = selectedAlgoDetail.extra;
  123. const extraJSON = JSON.parse(extraStr);
  124. const nextRegionJudge =
  125. extraJSON.inferParams?.[0]?.regionJudge === RegionJudge.out
  126. ? RegionJudge.in
  127. : RegionJudge.out;
  128. extraJSON.inferParams[0].regionJudge = nextRegionJudge;
  129. const newParam = {
  130. cameraId: cameraId,
  131. algoId: selectedAlgoDetail.algoId,
  132. extra: JSON.stringify(extraJSON),
  133. id: selectedAlgoDetail.id!,
  134. };
  135. updateCameraAlgoApi(newParam).then(() => {
  136. ElMessage.success('更新成功');
  137. getCameraAlgoList(cameraId);
  138. });
  139. };
  140. const handleSave = () => {
  141. const json = fenceEditorRef.value?.toObject();
  142. console.log('save json', json);
  143. const cameraId = cameraDetailStore.cameraId;
  144. if (!cameraId) {
  145. ElMessage.error('未选中相机');
  146. return;
  147. }
  148. const algoId = cameraAlgoStore.selectedAlgoId;
  149. if (!algoId) {
  150. ElMessage.error('未选中算法');
  151. return;
  152. }
  153. const presetToken = presetStore.currentPresetToken;
  154. if (!presetToken) {
  155. ElMessage.error('未选中预置位');
  156. return;
  157. }
  158. fenceStore
  159. .saveFence({
  160. cameraId: cameraId,
  161. algoId: algoId,
  162. presetToken,
  163. electronicFencePolygon: JSON.stringify(json),
  164. })
  165. ?.then(() => {
  166. ElMessage.success('更新成功');
  167. });
  168. };
  169. // const handleUpdateViewType = (t: ViewType) => {
  170. // console.log('viewType', t);
  171. // };
  172. const drawable = computed(() => {
  173. if (!presetStore.currentPresetToken) return false;
  174. if (!cameraAlgoStore.selectedAlgoId) return false;
  175. if (!cameraAlgoStore.selectedAlgoDetail?.electronicFenceBool) return false;
  176. return true;
  177. });
  178. watchEffect(() => {
  179. const electronicFenceBool = cameraAlgoStore.selectedAlgoDetail?.electronicFenceBool;
  180. if (presetStore.currentPresetToken && cameraAlgoStore.selectedAlgoId && electronicFenceBool) {
  181. const points = fenceStore.serverFencePoints || [];
  182. if (!points) {
  183. fenceEditorRef.value?.clear();
  184. return;
  185. }
  186. /** 先清空原有的 */
  187. fenceEditorRef.value?.clear();
  188. // fenceEditorRef.value?.createLines(rawLinePoints);
  189. fenceEditorRef.value?.setEditMode();
  190. isEdit.value = true;
  191. return;
  192. } else {
  193. fenceEditorRef.value?.clear();
  194. fenceEditorRef.value?.exitEditMode();
  195. isEdit.value = false;
  196. }
  197. });
  198. const handleAddPreset = () => {
  199. addPresetModalVisible.value = true;
  200. };
  201. </script>
  202. <style scoped>
  203. .cameraViewSettingWrapper {
  204. position: relative;
  205. /* border: 1px solid #ccc; */
  206. }
  207. .cameraViewOverflow {
  208. overflow: hidden;
  209. position: relative;
  210. }
  211. .cameraVideo {
  212. position: absolute;
  213. top: 0;
  214. left: 0;
  215. z-index: 8;
  216. background: #ccc;
  217. width: 100%;
  218. height: 100%;
  219. }
  220. .toolbarWrapper {
  221. display: flex;
  222. align-items: center;
  223. /* margin-left: 25px; */
  224. position: relative;
  225. }
  226. .presetAddWrapper {
  227. position: absolute;
  228. bottom: 50px;
  229. right: 50px;
  230. flex-direction: column;
  231. display: flex;
  232. align-items: center;
  233. z-index: 10;
  234. }
  235. .cameraParamsSettingWrapper {
  236. display: flex;
  237. margin-top: 10px;
  238. }
  239. .algorithmsSetting {
  240. flex: 1;
  241. min-height: 300px;
  242. margin-left: 15px;
  243. /* border-left: 1px solid #ccc; */
  244. /* padding-left: 15px; */
  245. }
  246. .cameraParamsSetting {
  247. flex-basis: 330px;
  248. flex-shrink: 0;
  249. }
  250. .hidePresetControlCls {
  251. display: none;
  252. }
  253. .fenceEditorWrapper {
  254. position: relative;
  255. z-index: 9;
  256. }
  257. .presetWrapper {
  258. width: 962px;
  259. padding: 20px;
  260. padding-left: 15px;
  261. border-bottom: 1px solid #ccc;
  262. padding-bottom: 10px;
  263. margin-bottom: 15px;
  264. display: flex;
  265. justify-content: space-between;
  266. }
  267. </style>