CameraConfigGroup.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <template>
  2. <div class="cameraConfigGroup">
  3. <el-card>
  4. <template #header>
  5. <el-button
  6. type="primary"
  7. @click="createGroupDialog = true"
  8. style="margin-top: 24px; margin-bottom: 16px; width: 138px"
  9. >
  10. <img src="@/assets/images/create.png" style="margin-top: -1px; margin-right: 5px" />新建相机分组
  11. </el-button>
  12. </template>
  13. <el-table
  14. :data="cameraGroupList"
  15. :span-method="objectSpanMethod"
  16. height="calc(100vh - 380px)"
  17. style="width: 100%; margin-top: 16px; --el-table-border-color: none"
  18. v-loading="loading"
  19. >
  20. <el-table-column prop="id" label="组序号" width="70"/>
  21. <el-table-column prop="cameraName" label="相机名称" align="center">
  22. <template #default="scope">
  23. <div class="cameraName-text" v-if="scope.row.isMainCamera === IsMainCamera.YES">
  24. <el-icon><Star color="Gold" /></el-icon>
  25. {{ scope.row.cameraName }}
  26. </div>
  27. </template>
  28. </el-table-column>
  29. <el-table-column prop="cameraCode" label="设备ID"/>
  30. <el-table-column prop="location" label="地点"/>
  31. <el-table-column prop="algoName" label="算法">
  32. <template #default="scope">
  33. <div class="algoId-text" @click="handleView(scope.row)">
  34. {{ scope.row.algoName }}
  35. </div>
  36. </template>
  37. </el-table-column>
  38. <el-table-column label="操作" fixed="right" width="120px">
  39. <template #default="scope">
  40. <div class="operation">
  41. <el-tooltip effect="light" content="关闭/开启" placement="bottom">
  42. <el-switch
  43. :model-value="scope.row.status"
  44. :inactive-value="CameraGroupStatus.CLOSE"
  45. :active-value="CameraGroupStatus.OPEN"
  46. @update:model-value="(val) => handleSwitch(val, scope.row)"/>
  47. </el-tooltip>
  48. <el-tooltip effect="light" content="删除" placement="bottom">
  49. <img src="@/views/message/alarmMessages/img/delete.png" @click="handleDelete(scope.row)" />
  50. </el-tooltip>
  51. </div>
  52. </template>
  53. </el-table-column>
  54. <template #empty>
  55. <div class="emptyDiv">
  56. <img src="@/assets/images/empty.png" class="emptyImg" />
  57. <span class="emptySpan">暂无数据</span>
  58. </div>
  59. </template>
  60. </el-table>
  61. <section class="mt-4 flex justify-end">
  62. <el-pagination
  63. background
  64. layout="total, sizes, prev, pager, next"
  65. :page-sizes="[10, 30, 50]"
  66. :total="total"
  67. v-model:page-size="requestParams.pageSize"
  68. v-model:current-page="requestParams.pageNumber"
  69. @change="queryCameraGroupPage"
  70. />
  71. </section>
  72. </el-card>
  73. <!--删除弹窗 -->
  74. <el-dialog v-model="deleteDialog" width="424px" top="20%" class="deleteDialog">
  75. <template #header="">
  76. <div class="deleteDialogHeader">
  77. <img src="@/assets/images/deleteTip.png" class="deleteTip" />
  78. <span class="titleSpan">请确认删除该相机分组吗?</span>
  79. </div>
  80. </template>
  81. <span style="margin-left: 37px">删除之后,该组多相机检测将失效!</span>
  82. <div class="dialogBottom">
  83. <el-button class="dialogBtn" @click="deleteDialog = false">取消</el-button>
  84. <el-button class="dialogBtn" type="primary" @click="confirmDelete">确定</el-button>
  85. </div>
  86. </el-dialog>
  87. <!-- 新增相机分组弹窗 -->
  88. <el-dialog v-model="createGroupDialog" width="70%" top="15%" left="25%" class="deleteDialog" title="设置相机组">
  89. <SettingCamera ref="settingCameraRef"/>
  90. <div class="dialogBottom">
  91. <el-button class="dialogBtn" @click="handleCancle">取消</el-button>
  92. <el-button class="dialogBtn" type="primary" @click="handleCreateGroup">确定</el-button>
  93. </div>
  94. </el-dialog>
  95. </div>
  96. </template>
  97. <script lang="ts" setup>
  98. import { onMounted, ref } from 'vue';
  99. import { useRouter } from 'vue-router';
  100. import { ElMessage } from 'element-plus';
  101. import { Star } from '@element-plus/icons-vue';
  102. import useCameraGroupQuery from './hooks/useCameraGroupQuery';
  103. import { CameraGroupTableItem, CameraGroupStatus, IsMainCamera } from '@/types/camera/camera-preview';
  104. import { deleteDetectionGroup, updateGroupStatus, saveDetectionGroup } from '@/api/camera/camera-preview-group';
  105. import SettingCamera from './components/SettingCamera.vue'
  106. const router = useRouter();
  107. const { requestParams, total, queryCameraGroupPage, cameraGroupList, loading } = useCameraGroupQuery();
  108. const createGroupDialog = ref(false);
  109. const deleteDialog = ref(false);
  110. const cameraDetectionGroupId = ref();
  111. const objectSpanMethod = ({
  112. row,
  113. rowIndex,
  114. columnIndex,
  115. }) => {
  116. // 合并组序列和操作列
  117. if (columnIndex === 0 || columnIndex === 5) {
  118. const list = cameraGroupList.value;
  119. const groupId = row.cameraDetectionGroupId;
  120. const firstIndex = list.findIndex(item => item.cameraDetectionGroupId === groupId);
  121. if (rowIndex !== firstIndex) {
  122. return { rowspan: 0, colspan: 0 };
  123. }
  124. let rowCount = 0;
  125. for (let i = firstIndex; i < list.length; i++) {
  126. if (list[i].cameraDetectionGroupId === groupId) rowCount++;
  127. else break;
  128. }
  129. return {
  130. rowspan: rowCount,
  131. colspan: 1
  132. };
  133. }
  134. };
  135. const handleDelete = (row: CameraGroupTableItem) => {
  136. if (row.status === CameraGroupStatus.OPEN) {
  137. ElMessage({
  138. message: '开启状态的分组不可删除',
  139. type: 'warning',
  140. plain: true,
  141. });
  142. } else {
  143. deleteDialog.value = true;
  144. cameraDetectionGroupId.value = row.cameraDetectionGroupId;
  145. }
  146. }
  147. const handleSwitch = (newStatus: number, row: CameraGroupTableItem) => {
  148. const data = {
  149. cameraDetectionGroupId: row.cameraDetectionGroupId,
  150. status: newStatus,
  151. }
  152. updateGroupStatus(data).then(res => {
  153. ElMessage.success('操作成功')
  154. queryCameraGroupPage();
  155. })
  156. }
  157. const confirmDelete = () => {
  158. deleteDetectionGroup([Number(cameraDetectionGroupId.value)]).then(() => {
  159. ElMessage({
  160. message: '删除成功',
  161. type: 'success',
  162. plain: true,
  163. });
  164. deleteDialog.value = false;
  165. queryCameraGroupPage();
  166. })
  167. }
  168. const settingCameraRef = ref<InstanceType<typeof SettingCamera>>();
  169. const handleCreateGroup = () => {
  170. const { valid, data } = settingCameraRef.value?.isValidate();
  171. if(valid) {
  172. // 执行提交逻辑
  173. const saveData = data.map(item => {
  174. return {
  175. cameraId: Number(item.code),
  176. algoId: Number(item.algoCode),
  177. isMainCamera: item.isMainCamera,
  178. }
  179. })
  180. saveDetectionGroup(saveData).then(() => {
  181. ElMessage({
  182. message: '相机组添加成功',
  183. type:'success',
  184. plain: true,
  185. });
  186. createGroupDialog.value = false;
  187. settingCameraRef.value?.clearForm();
  188. queryCameraGroupPage();
  189. })
  190. }
  191. }
  192. const handleCancle = () => {
  193. createGroupDialog.value = false
  194. settingCameraRef.value?.clearForm();
  195. }
  196. const handleView = (row: CameraGroupTableItem) => {
  197. router.push({
  198. path: '/algorithm/module-camera',
  199. query: {
  200. groupId: row.cameraDetectionGroupId,
  201. }
  202. })
  203. }
  204. onMounted(() => {
  205. queryCameraGroupPage();
  206. })
  207. </script>
  208. <style lang="scss" scoped>
  209. .emptyDiv {
  210. margin-top: 78px;
  211. margin: auto;
  212. width: 396px;
  213. .emptyImg {
  214. height: 257px;
  215. }
  216. .emptySpan {
  217. font-family: PingFangSC, PingFang SC;
  218. font-weight: 400;
  219. font-size: 18px;
  220. color: rgba(0, 0, 0, 0.45);
  221. text-align: left;
  222. font-style: normal;
  223. }
  224. }
  225. .algoId-text {
  226. cursor: pointer;
  227. color: #409eff;
  228. }
  229. .deleteDialog {
  230. .deleteDialogHeader {
  231. display: flex;
  232. .deleteTip {
  233. height: 24px;
  234. width: 24px;
  235. }
  236. .titleSpan {
  237. height: 24px;
  238. font-size: 16px;
  239. color: rgba(0, 0, 0, 0.88);
  240. line-height: 24px;
  241. text-align: center;
  242. margin-left: 12px;
  243. }
  244. }
  245. .dialogBottom {
  246. display: flex;
  247. justify-content: flex-end;
  248. margin-top: 12px;
  249. }
  250. }
  251. .operation {
  252. display: flex;
  253. align-items: center;
  254. img {
  255. margin-left: 20px;
  256. }
  257. }
  258. </style>