feat: 增加信令自动重连保活与控制端视频录制
- 信令客户端增加心跳保活与指数退避自动重连机制 - 服务端优化传输异常日志级别,客户端断开不再报错 - 被控端信令断开时保持服务运行并自动重连 - Flutter 控制端增加远程视频录制功能,兼容标准 WebRTC 模式切换 - 各端连接按钮增加“连接中”状态防重复点击
This commit is contained in:
@@ -31,8 +31,10 @@ function onConnectDevice() {
|
||||
<input class="input" v-model="store.deviceId" placeholder="例如 web-controller-001" />
|
||||
</div>
|
||||
|
||||
<button class="btn" v-if="!store.signalingConnected" @click="connectSignaling">连接信令服务器</button>
|
||||
<button class="btn danger" v-else @click="disconnectSignaling">断开信令</button>
|
||||
<button class="btn danger" v-if="store.signalingConnected" @click="disconnectSignaling">断开信令服务器</button>
|
||||
<button class="btn" v-else :disabled="store.signalingConnecting" @click="connectSignaling">
|
||||
{{ store.signalingConnecting ? '正在连接...' : '连接信令服务器' }}
|
||||
</button>
|
||||
|
||||
<div class="section-title">被控端设备 (CONTROLLED)</div>
|
||||
<button class="btn secondary" style="margin-bottom:12px" @click="refreshDevices" :disabled="!store.signalingConnected">
|
||||
|
||||
@@ -19,3 +19,33 @@ import { store } from '../store/controllerStore';
|
||||
<span>目标: <b>{{ store.targetDeviceId || '-' }}</b></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.stats-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.stats-bar span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 每个统计项固定宽度,避免文字多少导致整体跳动 */
|
||||
.stats-bar span:nth-child(1) { width: 140px; } /* 分辨率 */
|
||||
.stats-bar span:nth-child(2) { width: 90px; } /* 帧率 */
|
||||
.stats-bar span:nth-child(3) { width: 110px; } /* 编码 */
|
||||
.stats-bar span:nth-child(4) { width: 100px; } /* 延迟 */
|
||||
.stats-bar span:nth-child(5) { width: 100px; } /* 抖动 */
|
||||
.stats-bar span:nth-child(6) { width: 100px; } /* 丢帧 */
|
||||
.stats-bar span:nth-child(7) { width: 120px; } /* 解码耗时 */
|
||||
.stats-bar span:nth-child(8) { width: 120px; } /* 上传 */
|
||||
.stats-bar span:nth-child(9) { width: 120px; } /* 下载 */
|
||||
.stats-bar span:nth-child(10) { width: 100px; } /* 丢包 */
|
||||
.stats-bar span:nth-child(11) { width: 120px; } /* 时长 */
|
||||
.stats-bar span:nth-child(12) { width: 140px; } /* 控制通道 */
|
||||
.stats-bar span:nth-child(13) { width: 160px; } /* 目标 */
|
||||
</style>
|
||||
|
||||
@@ -26,6 +26,7 @@ export const store = reactive({
|
||||
|
||||
protoReady: false,
|
||||
signalingConnected: false,
|
||||
signalingConnecting: false,
|
||||
registered: false,
|
||||
rtcConnected: false,
|
||||
dataChannelOpen: false,
|
||||
@@ -60,20 +61,26 @@ export function connectSignaling() {
|
||||
const deviceId = store.deviceId.trim();
|
||||
if (!deviceId) { store.error = '请填写本机设备 ID'; return; }
|
||||
|
||||
store.signalingConnecting = true;
|
||||
signaling = new SignalingClient({
|
||||
serverUrl: store.serverUrl.trim(),
|
||||
deviceId,
|
||||
onConnected: () => {
|
||||
store.signalingConnected = true;
|
||||
store.signalingConnecting = false;
|
||||
store.statusText = '已连接信令服务器';
|
||||
refreshDevices();
|
||||
},
|
||||
onDisconnected: () => {
|
||||
store.signalingConnected = false;
|
||||
store.signalingConnecting = false;
|
||||
store.registered = false;
|
||||
store.statusText = '已断开信令连接';
|
||||
},
|
||||
onError: (e) => { store.error = '信令错误: ' + e; },
|
||||
onError: (e) => {
|
||||
store.signalingConnecting = false;
|
||||
store.error = '信令错误: ' + e;
|
||||
},
|
||||
onMessage: handleSignalMessage,
|
||||
});
|
||||
signaling.connect();
|
||||
@@ -172,6 +179,7 @@ export function disconnectSignaling() {
|
||||
disconnectDevice();
|
||||
if (signaling) { signaling.disconnect(); signaling = null; }
|
||||
store.signalingConnected = false;
|
||||
store.signalingConnecting = false;
|
||||
store.registered = false;
|
||||
store.controlledDevices = [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user