PTZController.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. import { startPTZ, stopPTZ, type PTZConfig } from '@/api/ptz'
  4. const props = withDefaults(
  5. defineProps<{
  6. /** 摄像头配置 */
  7. config?: PTZConfig
  8. }>(),
  9. {
  10. config: () => ({
  11. host: '192.168.0.64',
  12. username: 'admin',
  13. password: 'Wxc767718929',
  14. channel: 1
  15. })
  16. }
  17. )
  18. const isMoving = ref(false)
  19. const currentDirection = ref<string | null>(null)
  20. // 开始移动
  21. async function handleStart(
  22. direction: 'UP' | 'DOWN' | 'LEFT' | 'RIGHT' | 'UP_LEFT' | 'UP_RIGHT' | 'DOWN_LEFT' | 'DOWN_RIGHT'
  23. ) {
  24. if (isMoving.value) return
  25. isMoving.value = true
  26. currentDirection.value = direction
  27. const result = await startPTZ(props.config, direction)
  28. if (!result.success) {
  29. console.error('PTZ 控制失败:', result.error)
  30. }
  31. }
  32. // 停止移动
  33. async function handleStop() {
  34. if (!isMoving.value) return
  35. const result = await stopPTZ(props.config)
  36. if (!result.success) {
  37. console.error('PTZ 停止失败:', result.error)
  38. }
  39. isMoving.value = false
  40. currentDirection.value = null
  41. }
  42. </script>
  43. <template>
  44. <div class="ptz-controller">
  45. <div class="ptz-grid">
  46. <!-- 第一行 -->
  47. <button class="ptz-btn corner" @mousedown="handleStart('UP_LEFT')" @mouseup="handleStop" @mouseleave="handleStop">
  48. <el-icon><i-ep-top-left /></el-icon>
  49. </button>
  50. <button class="ptz-btn" @mousedown="handleStart('UP')" @mouseup="handleStop" @mouseleave="handleStop">
  51. <el-icon><i-ep-arrow-up /></el-icon>
  52. </button>
  53. <button
  54. class="ptz-btn corner"
  55. @mousedown="handleStart('UP_RIGHT')"
  56. @mouseup="handleStop"
  57. @mouseleave="handleStop"
  58. >
  59. <el-icon><i-ep-top-right /></el-icon>
  60. </button>
  61. <!-- 第二行 -->
  62. <button class="ptz-btn" @mousedown="handleStart('LEFT')" @mouseup="handleStop" @mouseleave="handleStop">
  63. <el-icon><i-ep-arrow-left /></el-icon>
  64. </button>
  65. <div class="ptz-center">
  66. <el-icon v-if="isMoving" class="spinning"><i-ep-loading /></el-icon>
  67. <span v-else>PTZ</span>
  68. </div>
  69. <button class="ptz-btn" @mousedown="handleStart('RIGHT')" @mouseup="handleStop" @mouseleave="handleStop">
  70. <el-icon><i-ep-arrow-right /></el-icon>
  71. </button>
  72. <!-- 第三行 -->
  73. <button
  74. class="ptz-btn corner"
  75. @mousedown="handleStart('DOWN_LEFT')"
  76. @mouseup="handleStop"
  77. @mouseleave="handleStop"
  78. >
  79. <el-icon><i-ep-bottom-left /></el-icon>
  80. </button>
  81. <button class="ptz-btn" @mousedown="handleStart('DOWN')" @mouseup="handleStop" @mouseleave="handleStop">
  82. <el-icon><i-ep-arrow-down /></el-icon>
  83. </button>
  84. <button
  85. class="ptz-btn corner"
  86. @mousedown="handleStart('DOWN_RIGHT')"
  87. @mouseup="handleStop"
  88. @mouseleave="handleStop"
  89. >
  90. <el-icon><i-ep-bottom-right /></el-icon>
  91. </button>
  92. </div>
  93. </div>
  94. </template>
  95. <style scoped lang="scss">
  96. .ptz-controller {
  97. display: inline-block;
  98. }
  99. .ptz-grid {
  100. display: grid;
  101. grid-template-columns: repeat(3, 48px);
  102. gap: 4px;
  103. }
  104. .ptz-btn {
  105. width: 48px;
  106. height: 48px;
  107. border: 1px solid var(--el-border-color);
  108. border-radius: var(--radius-base);
  109. background: var(--el-bg-color);
  110. cursor: pointer;
  111. display: flex;
  112. align-items: center;
  113. justify-content: center;
  114. font-size: 20px;
  115. color: var(--el-text-color-primary);
  116. transition: all 0.2s;
  117. &:hover {
  118. background: var(--el-color-primary-light-9);
  119. border-color: var(--el-color-primary);
  120. }
  121. &:active {
  122. background: var(--el-color-primary-light-7);
  123. }
  124. &.corner {
  125. font-size: 16px;
  126. }
  127. }
  128. .ptz-center {
  129. width: 48px;
  130. height: 48px;
  131. border-radius: 50%;
  132. background: var(--el-color-primary-light-9);
  133. border: 2px solid var(--el-color-primary);
  134. display: flex;
  135. align-items: center;
  136. justify-content: center;
  137. font-size: 12px;
  138. font-weight: bold;
  139. color: var(--el-color-primary);
  140. }
  141. .spinning {
  142. animation: spin 1s linear infinite;
  143. }
  144. @keyframes spin {
  145. from {
  146. transform: rotate(0deg);
  147. }
  148. to {
  149. transform: rotate(360deg);
  150. }
  151. }
  152. </style>