FenceToolbar.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <template>
  2. <div class="fenceWrapper">
  3. <div>
  4. <div>电子围栏</div>
  5. <ElSwitch size="small" class="fenceSwitchBtn" />
  6. </div>
  7. <PresetSelect />
  8. <div style="display: flex">
  9. <ElCheckbox label="检测围栏外部" v-model="isFenceRegionOut" @update:modelValue="handleUpdateRegion" />
  10. <ElCheckbox label="前台画面显示" v-model="isDisplayFenceInVideo" @update:modelValue="handleUpdateDisplay" />
  11. <a :href="previewUrl" target="_blank" style="margin-left: 20px" v-if="previewUrl && false">平台相机预览</a>
  12. </div>
  13. <div class="fenceListWrapper">
  14. <FenceNameItem
  15. :active="item.id === fenceStore.currentFenceId"
  16. v-for="item in fenceStore.allFences"
  17. :detail="item"
  18. :key="item.id"
  19. @click="handleSelectFence(item.id)"
  20. @delete="handleDeleteFence"
  21. @edit="handleEditFenceInfo(item)"
  22. />
  23. </div>
  24. <div>
  25. <EditFenceDialog
  26. v-if="showEditFenceDialog"
  27. @cancel="handleEditCancel"
  28. @submit="handleEditSubmit"
  29. :detail="selectedDetail"
  30. />
  31. </div>
  32. <!-- <div class="toolbar"> -->
  33. <!-- <div class="fenceDrawingTip" v-if="isEdit">
  34. {{ cameraAlgoStore.selectedAlgoDetail?.algoInfo?.name }}算法电子围栏绘制中
  35. </div> -->
  36. <!-- <template v-if="props.isEdit"> -->
  37. <!-- <ToolbarIcon
  38. :src="deleteIcon"
  39. :active="false"
  40. @click="emits('toggleFence')"
  41. tip="检测范围反选"
  42. /> -->
  43. <!-- <ToggleFenceStatus @click="emits('toggleRange')" />
  44. <ToolbarIcon :src="deleteIcon" :active="false" @click="emits('remove')" tip="删除电子围栏" />
  45. <ToolbarIcon :src="saveIcon" :active="false" @click="emits('save')" tip="保存电子围栏" />
  46. </template> -->
  47. <!-- <ElButton type="primary" size="small" @click="toggleEdit">{{
  48. props.isEdit ? '退出编辑' : '编辑电子围栏'
  49. }}</ElButton> -->
  50. <!-- </div> -->
  51. </div>
  52. </template>
  53. <script setup lang="ts">
  54. import { computed, defineEmits, ref, watch } from 'vue';
  55. import { ElButton, ElSwitch } from 'element-plus';
  56. import ToolbarIcon from '../ToolbarIcon/ToolbarIcon.vue';
  57. import saveIcon from '@/assets/images/camera/save.png';
  58. import deleteIcon from '@/assets/images/camera/delete.png';
  59. import ToggleFenceStatus from './ToggleFenceStatus.vue';
  60. import useCameraAlgoStore from '../../store/useCameraAlgoStore';
  61. import PresetSelect from '../PresetSelect/PresetSelect.vue';
  62. import FenceNameItem from './FenceNameItem.vue';
  63. import useFenceStore from '../../store/useFenceStore';
  64. import useCameraDetailStore from '../../store/useCameraDetailStore';
  65. import usePresetListStore from '../../store/usePresetListStore';
  66. import EditFenceDialog from './EditFenceDialog.vue';
  67. import { ServerLineInfo } from '../FenceEditor/constants';
  68. import { storeToRefs } from 'pinia';
  69. import { RegionJudge } from './constants';
  70. import { choosePreset, updateFenceDisplayStatus } from '@/api/camera/camera-preview';
  71. import { FenceDisplayStatus } from '@/types/camera/constant';
  72. import { useGlobSetting } from '@/hooks/setting';
  73. const cameraAlgoStore = useCameraAlgoStore();
  74. const fenceStore = useFenceStore();
  75. const cameraDetailStore = useCameraDetailStore();
  76. const presetStore = usePresetListStore();
  77. const props = defineProps<{ isEdit: boolean }>();
  78. const showEditFenceDialog = ref(false);
  79. const selectedDetail = ref<ServerLineInfo | null>(null);
  80. const { selectedAlgoDetail } = storeToRefs(cameraAlgoStore);
  81. const emits = defineEmits<{
  82. (e: 'toggleEditable', editState: boolean): unknown;
  83. (e: 'toggleRange'): unknown;
  84. (e: 'remove'): unknown;
  85. (e: 'save'): unknown;
  86. (e: 'select', fenceId: number): unknown;
  87. }>();
  88. const isFenceRegionOut = ref(false);
  89. const isDisplayFenceInVideo = ref(false);
  90. const { detail } = storeToRefs(cameraDetailStore);
  91. const { appPCUrl } = useGlobSetting();
  92. const previewUrl = computed(() => {
  93. const firstSceneId = detail.value?.sceneTemplateList[0]?.sceneId;
  94. if (!detail.value?.workshopId || !detail.value?.code || !firstSceneId) return '';
  95. return appPCUrl + `#/shop?id=${detail.value?.workshopId}&cameraCode=${detail.value?.code!}&sceneId=${firstSceneId}`;
  96. });
  97. watch(
  98. () => selectedAlgoDetail.value?.regionJudge,
  99. (newVal) => {
  100. isFenceRegionOut.value = newVal === RegionJudge.out;
  101. },
  102. {
  103. immediate: true,
  104. },
  105. );
  106. watch(
  107. () => cameraDetailStore.isShowFence,
  108. (isShowFence) => {
  109. isDisplayFenceInVideo.value = isShowFence;
  110. },
  111. {
  112. immediate: true,
  113. },
  114. );
  115. const toggleEdit = () => {
  116. emits('toggleEditable', !props.isEdit);
  117. };
  118. const handleSelectFence = (nextFenceId: number) => {
  119. emits('select', nextFenceId);
  120. };
  121. const handleUpdateRegion = (val: string) => {
  122. console.log('isFenceRegionOut', isFenceRegionOut.value);
  123. console.log('region', val);
  124. emits('toggleRange');
  125. };
  126. const handleEditFenceInfo = (detail) => {
  127. showEditFenceDialog.value = true;
  128. selectedDetail.value = detail;
  129. };
  130. const handleEditCancel = () => {
  131. showEditFenceDialog.value = false;
  132. selectedDetail.value = null;
  133. };
  134. const handleDeleteFence = (fenceId: number) => {
  135. const cameraId = cameraDetailStore.cameraId;
  136. const algoId = cameraAlgoStore.selectedAlgoId!;
  137. const presetToken = presetStore.currentPresetToken;
  138. fenceStore.deleteFence({ cameraId, algoId, presetToken, fenceId });
  139. };
  140. const handleEditSubmit = (data: { label: string; name: string }) => {
  141. const cameraId = cameraDetailStore.cameraId;
  142. const algoId = cameraAlgoStore.selectedAlgoId!;
  143. const presetToken = presetStore.currentPresetToken;
  144. const fenceId = selectedDetail.value?.id;
  145. if (!fenceId) return;
  146. fenceStore
  147. .editFence({
  148. cameraId,
  149. algoId,
  150. presetToken,
  151. fenceId: fenceId,
  152. fenceLabel: data.label,
  153. fenceName: data.name,
  154. })
  155. .then(() => {
  156. handleEditCancel();
  157. });
  158. };
  159. const handleUpdateDisplay = (nextStatus: boolean) => {
  160. const params = {
  161. cameraCode: cameraDetailStore.detail?.code!,
  162. isDisplayFence: nextStatus ? FenceDisplayStatus.enabled : FenceDisplayStatus.disabled,
  163. };
  164. updateFenceDisplayStatus(params);
  165. if (nextStatus) {
  166. // 由于历史原因,需要调用两次接口
  167. const cameraId = cameraDetailStore.cameraId;
  168. const algoId = cameraAlgoStore.selectedAlgoId!;
  169. const presetToken = presetStore.currentPresetToken;
  170. const params = {
  171. algoId,
  172. cameraId,
  173. presetToken,
  174. };
  175. choosePreset(params);
  176. }
  177. };
  178. </script>
  179. <style scoped>
  180. .toolbar {
  181. display: flex;
  182. align-items: center;
  183. z-index: 10;
  184. padding: 5px;
  185. border-radius: 50px;
  186. }
  187. .fenceDrawingTip {
  188. background: #e8f5ff;
  189. border-radius: 6px;
  190. border: 1px solid #bae0ff;
  191. text-align: center;
  192. font-size: 12px;
  193. padding: 2px 20px;
  194. margin-right: 30px;
  195. color: #1890ff;
  196. }
  197. .fenceSwitchBtn {
  198. position: absolute;
  199. right: 10px;
  200. top: 10px;
  201. }
  202. .fenceWrapper {
  203. padding: 10px;
  204. }
  205. .fenceListWrapper {
  206. max-height: 435px;
  207. overflow-y: auto;
  208. }
  209. </style>