|
|
@@ -97,29 +97,37 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
+ <!-- 速度控制 -->
|
|
|
+ <div class="speed-control">
|
|
|
+ <div class="control-label">
|
|
|
+ <span>速度: {{ ptzSpeed }}</span>
|
|
|
+ </div>
|
|
|
+ <el-slider
|
|
|
+ v-model="ptzSpeed"
|
|
|
+ :min="10"
|
|
|
+ :max="100"
|
|
|
+ :step="10"
|
|
|
+ :show-tooltip="true"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 缩放控制 -->
|
|
|
<div class="zoom-controls">
|
|
|
- <div class="zoom-label">缩放</div>
|
|
|
- <div class="zoom-btns">
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- :icon="ZoomIn"
|
|
|
- @mousedown="handleZoom('IN')"
|
|
|
- @mouseup="handleZoomStop"
|
|
|
- @mouseleave="handleZoomStop"
|
|
|
- >
|
|
|
- 放大
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- :icon="ZoomOut"
|
|
|
- @mousedown="handleZoom('OUT')"
|
|
|
- @mouseup="handleZoomStop"
|
|
|
- @mouseleave="handleZoomStop"
|
|
|
- >
|
|
|
- 缩小
|
|
|
- </el-button>
|
|
|
+ <div class="zoom-header">
|
|
|
+ <el-icon><ZoomOut /></el-icon>
|
|
|
+ <span>缩放</span>
|
|
|
+ <el-icon><ZoomIn /></el-icon>
|
|
|
</div>
|
|
|
+ <el-slider
|
|
|
+ v-model="zoomValue"
|
|
|
+ :min="-100"
|
|
|
+ :max="100"
|
|
|
+ :step="10"
|
|
|
+ :show-tooltip="true"
|
|
|
+ :format-tooltip="formatZoomTooltip"
|
|
|
+ @input="handleZoomChange"
|
|
|
+ @change="handleZoomRelease"
|
|
|
+ />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -246,6 +254,10 @@ const ptzConfig = reactive({
|
|
|
password: 'Wxc767718929'
|
|
|
})
|
|
|
|
|
|
+// PTZ 速度和缩放
|
|
|
+const ptzSpeed = ref(50)
|
|
|
+const zoomValue = ref(0)
|
|
|
+
|
|
|
// 播放状态
|
|
|
const isPlaying = ref(false)
|
|
|
|
|
|
@@ -384,11 +396,12 @@ async function handlePTZ(direction: keyof typeof PTZ_DIRECTIONS) {
|
|
|
username: ptzConfig.username,
|
|
|
password: ptzConfig.password
|
|
|
},
|
|
|
- direction
|
|
|
+ direction,
|
|
|
+ ptzSpeed.value
|
|
|
)
|
|
|
|
|
|
if (result.success) {
|
|
|
- addLog(`PTZ 移动: ${direction}`, 'info')
|
|
|
+ addLog(`PTZ 移动: ${direction} (速度: ${ptzSpeed.value})`, 'info')
|
|
|
} else {
|
|
|
addLog(`PTZ 控制失败: ${result.error}`, 'error')
|
|
|
}
|
|
|
@@ -408,41 +421,49 @@ async function handlePTZStop() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 缩放控制
|
|
|
-async function handleZoom(direction: keyof typeof PTZ_ZOOM_DIRECTIONS) {
|
|
|
- if (!ptzConfig.host || !ptzConfig.username || !ptzConfig.password) {
|
|
|
- ElMessage.warning('请先配置摄像头信息')
|
|
|
+// 缩放滑块控制
|
|
|
+function formatZoomTooltip(val: number) {
|
|
|
+ if (val === 0) return '停止'
|
|
|
+ return val > 0 ? `放大 ${val}` : `缩小 ${Math.abs(val)}`
|
|
|
+}
|
|
|
+
|
|
|
+async function handleZoomChange(val: number) {
|
|
|
+ if (!ptzConfig.host || !ptzConfig.username || !ptzConfig.password) return
|
|
|
+
|
|
|
+ if (val === 0) {
|
|
|
+ await stopZoom({
|
|
|
+ host: ptzConfig.host,
|
|
|
+ username: ptzConfig.username,
|
|
|
+ password: ptzConfig.password
|
|
|
+ })
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- const result = await startZoom(
|
|
|
+ const direction = val > 0 ? 'IN' : 'OUT'
|
|
|
+ const speed = Math.abs(val)
|
|
|
+
|
|
|
+ await startZoom(
|
|
|
{
|
|
|
host: ptzConfig.host,
|
|
|
username: ptzConfig.username,
|
|
|
password: ptzConfig.password
|
|
|
},
|
|
|
- direction
|
|
|
+ direction,
|
|
|
+ speed
|
|
|
)
|
|
|
-
|
|
|
- if (result.success) {
|
|
|
- addLog(`缩放: ${direction === 'IN' ? '放大' : '缩小'}`, 'info')
|
|
|
- } else {
|
|
|
- addLog(`缩放失败: ${result.error}`, 'error')
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
-async function handleZoomStop() {
|
|
|
+async function handleZoomRelease() {
|
|
|
+ // 松开滑块时回到中间并停止
|
|
|
+ zoomValue.value = 0
|
|
|
if (!ptzConfig.host) return
|
|
|
|
|
|
- const result = await stopZoom({
|
|
|
+ await stopZoom({
|
|
|
host: ptzConfig.host,
|
|
|
username: ptzConfig.username,
|
|
|
password: ptzConfig.password
|
|
|
})
|
|
|
-
|
|
|
- if (!result.success) {
|
|
|
- addLog(`缩放停止失败: ${result.error}`, 'error')
|
|
|
- }
|
|
|
+ addLog('缩放停止', 'info')
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
@@ -563,23 +584,34 @@ async function handleZoomStop() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .zoom-controls {
|
|
|
+ .speed-control {
|
|
|
margin-top: 15px;
|
|
|
padding-top: 15px;
|
|
|
border-top: 1px solid var(--border-color);
|
|
|
|
|
|
- .zoom-label {
|
|
|
+ .control-label {
|
|
|
font-size: 12px;
|
|
|
color: var(--text-secondary);
|
|
|
- margin-bottom: 10px;
|
|
|
+ margin-bottom: 8px;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- .zoom-btns {
|
|
|
+ .zoom-controls {
|
|
|
+ margin-top: 15px;
|
|
|
+ padding-top: 15px;
|
|
|
+ border-top: 1px solid var(--border-color);
|
|
|
+
|
|
|
+ .zoom-header {
|
|
|
display: flex;
|
|
|
- gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--text-secondary);
|
|
|
+ margin-bottom: 8px;
|
|
|
|
|
|
- .el-button {
|
|
|
+ span {
|
|
|
flex: 1;
|
|
|
+ text-align: center;
|
|
|
}
|
|
|
}
|
|
|
}
|