feat: 增加密码连接

This commit is contained in:
2026-07-22 20:32:52 +08:00
parent ef786b1529
commit bdde6ccd2e
19 changed files with 541 additions and 25 deletions

View File

@@ -3,9 +3,19 @@ import { ref } from 'vue';
import { store, connectSignaling, disconnectSignaling, refreshDevices, connectToDevice, disconnectDevice } from '../store/controllerStore';
const selected = ref('');
const authType = ref('CODE');
const authValue = ref('');
function onConnectDevice() {
connectToDevice(selected.value);
if (!selected.value) {
store.error = '请选择要连接的设备';
return;
}
if (!authValue.value.trim()) {
store.error = '请输入验证码或密码';
return;
}
connectToDevice(selected.value, authType.value, authValue.value.trim());
}
</script>
@@ -51,6 +61,15 @@ function onConnectDevice() {
</select>
</div>
<div class="section-title" style="margin-top:14px">连接鉴权</div>
<div class="auth-row">
<label class="auth-radio"><input type="radio" value="CODE" v-model="authType" /> 动态验证码</label>
<label class="auth-radio"><input type="radio" value="PASSWORD" v-model="authType" /> 固定密码</label>
</div>
<div class="field">
<input class="input" v-model="authValue" :placeholder="authType === 'PASSWORD' ? '请输入固定密码' : '请输入动态验证码'" />
</div>
<button class="btn" @click="onConnectDevice" :disabled="!selected || store.rtcConnected">发起远程控制</button>
<button class="btn danger" style="margin-top:12px" v-if="store.rtcConnected" @click="disconnectDevice">结束控制</button>
@@ -64,3 +83,8 @@ function onConnectDevice() {
</div>
</div>
</template>
<style scoped>
.auth-row { display: flex; gap: 16px; margin-bottom: 8px; align-items: center; }
.auth-radio { display: inline-flex; align-items: center; gap: 4px; }
</style>

View File

@@ -81,14 +81,17 @@ export class SignalingClient {
this.send({ type: 'DEVICE_LIST', fromDeviceId: this.deviceId });
}
sendOffer(sdp, toDeviceId) {
this.send({
sendOffer(sdp, toDeviceId, authType = null, authValue = null) {
const msg = {
type: 'OFFER',
fromDeviceId: this.deviceId,
toDeviceId,
deviceType: 'CONTROLLER',
payload: JSON.stringify({ sdp }),
});
};
if (authType) msg.authType = authType;
if (authValue != null) msg.authValue = authValue;
this.send(msg);
}
sendIceCandidate(candidate, toDeviceId) {

View File

@@ -35,7 +35,7 @@ export class WebRtcController {
this._pendingCandidates = [];
}
async createOffer() {
async createOffer(authType = null, authValue = null) {
this.pc = new RTCPeerConnection({ iceServers: this.iceServers });
this.pc.onicecandidate = (e) => {
@@ -88,7 +88,7 @@ export class WebRtcController {
const offer = await this.pc.createOffer();
await this.pc.setLocalDescription(offer);
this.signaling.sendOffer(this.pc.localDescription.sdp, this.targetDeviceId);
this.signaling.sendOffer(this.pc.localDescription.sdp, this.targetDeviceId, authType, authValue);
this._startStats();
}

View File

@@ -120,7 +120,7 @@ export function refreshDevices() {
signaling && signaling.requestDeviceList();
}
export async function connectToDevice(targetId) {
export async function connectToDevice(targetId, authType = null, authValue = null) {
if (!signaling || !store.signalingConnected) { store.error = '请先连接信令服务器'; return; }
if (!targetId) { store.error = '请选择要控制的被控端设备'; return; }
@@ -147,7 +147,7 @@ export async function connectToDevice(targetId) {
// 被控端上报当前实际采集分辨率,同步到 store 供 UI 展示/匹配预设。
onResolutionReport: (res) => { store.currentResolution = res; },
});
await webrtc.createOffer();
await webrtc.createOffer(authType, authValue);
} catch (e) {
// 捕获 createOffer 阶段的所有异常,避免未处理的 Promise 拒绝导致浏览器中断脚本执行、
// 间接影响 WebSocket 信令连接的存活。