|
@@ -1,76 +1,318 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div>
|
|
<div>
|
|
|
- <h1>当前是控制方</h1>
|
|
|
|
|
- <h1>https://github.com/galaxy-s10/billd-desk</h1>
|
|
|
|
|
- <div>
|
|
|
|
|
- 房间id:{{ roomId }},我的id:{{ mySocketId }},<n-button
|
|
|
|
|
- @click="copyToClipBoard(mySocketId)"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <h1>
|
|
|
|
|
+ 我的id:{{ mySocketId }},<n-button @click="copyToClipBoard(mySocketId)">
|
|
|
复制
|
|
复制
|
|
|
</n-button>
|
|
</n-button>
|
|
|
|
|
+ </h1>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <n-input-group>
|
|
|
|
|
+ <n-input-group-label>被控id</n-input-group-label>
|
|
|
|
|
+ <n-input
|
|
|
|
|
+ :style="{ width: '200px' }"
|
|
|
|
|
+ placeholder="请输入被控id"
|
|
|
|
|
+ v-model:value="receiverId"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <n-button
|
|
|
|
|
+ type="error"
|
|
|
|
|
+ @click="handleClose"
|
|
|
|
|
+ v-if="appStore.remoteDesk.isRemoteing"
|
|
|
|
|
+ >
|
|
|
|
|
+ 结束控制
|
|
|
|
|
+ </n-button>
|
|
|
|
|
+ <n-button
|
|
|
|
|
+ v-else
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ @click="handleRemote"
|
|
|
|
|
+ >
|
|
|
|
|
+ 开始远程
|
|
|
|
|
+ </n-button>
|
|
|
|
|
+ </n-input-group>
|
|
|
</div>
|
|
</div>
|
|
|
- <n-input-group>
|
|
|
|
|
- <n-input-group-label>被控id</n-input-group-label>
|
|
|
|
|
- <n-input
|
|
|
|
|
- :style="{ width: '200px' }"
|
|
|
|
|
- placeholder="请输入被控id"
|
|
|
|
|
- v-model:value="receiverId"
|
|
|
|
|
- />
|
|
|
|
|
- <n-button
|
|
|
|
|
- type="primary"
|
|
|
|
|
- @click="handleRemote"
|
|
|
|
|
- >
|
|
|
|
|
- 开始远程
|
|
|
|
|
- </n-button>
|
|
|
|
|
- <n-button @click="handleMoveMouse">移动鼠标</n-button>
|
|
|
|
|
- </n-input-group>
|
|
|
|
|
|
|
+
|
|
|
<div
|
|
<div
|
|
|
class="wrap"
|
|
class="wrap"
|
|
|
ref="remoteVideoRef"
|
|
ref="remoteVideoRef"
|
|
|
|
|
+ @mousedown="handleMouseDown"
|
|
|
|
|
+ @mousemove="handleMouseMove"
|
|
|
|
|
+ @mouseup="handleMouseUp"
|
|
|
|
|
+ @dblclick="handleDoublelclick"
|
|
|
|
|
+ @contextmenu="handleContextmenu"
|
|
|
></div>
|
|
></div>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
|
|
|
+import { Key } from '@nut-tree/shared';
|
|
|
import { copyToClipBoard, getRandomString } from 'billd-utils';
|
|
import { copyToClipBoard, getRandomString } from 'billd-utils';
|
|
|
-import { computed, onMounted, ref } from 'vue';
|
|
|
|
|
|
|
+import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
|
|
|
|
|
|
import { usePull } from '@/hooks/use-pull';
|
|
import { usePull } from '@/hooks/use-pull';
|
|
|
|
|
+import { useTip } from '@/hooks/use-tip';
|
|
|
|
|
+import { useAppStore } from '@/store/app';
|
|
|
import { useNetworkStore } from '@/store/network';
|
|
import { useNetworkStore } from '@/store/network';
|
|
|
import {
|
|
import {
|
|
|
|
|
+ RemoteDeskBehaviorEnum,
|
|
|
WsMsgTypeEnum,
|
|
WsMsgTypeEnum,
|
|
|
- WsRemoteDeskMoveMsgType,
|
|
|
|
|
|
|
+ WsRemoteDeskBehaviorType,
|
|
|
WsStartRemoteDesk,
|
|
WsStartRemoteDesk,
|
|
|
} from '@/types/websocket';
|
|
} from '@/types/websocket';
|
|
|
|
|
|
|
|
const num = '123456';
|
|
const num = '123456';
|
|
|
|
|
+const appStore = useAppStore();
|
|
|
const networkStore = useNetworkStore();
|
|
const networkStore = useNetworkStore();
|
|
|
const { videoWrapRef, initPull } = usePull(num);
|
|
const { videoWrapRef, initPull } = usePull(num);
|
|
|
|
|
+
|
|
|
const roomId = ref(num);
|
|
const roomId = ref(num);
|
|
|
const receiverId = ref('');
|
|
const receiverId = ref('');
|
|
|
const remoteVideoRef = ref<HTMLDivElement>();
|
|
const remoteVideoRef = ref<HTMLDivElement>();
|
|
|
-
|
|
|
|
|
|
|
+const isDown = ref(false);
|
|
|
|
|
+let clickTimer;
|
|
|
|
|
+let isLongClick = false;
|
|
|
const mySocketId = computed(() => {
|
|
const mySocketId = computed(() => {
|
|
|
return networkStore.wsMap.get(roomId.value)?.socketIo?.id || '-1';
|
|
return networkStore.wsMap.get(roomId.value)?.socketIo?.id || '-1';
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ window.removeEventListener('keydown', handleKeyDown);
|
|
|
|
|
+ handleClose();
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
initPull({
|
|
initPull({
|
|
|
isRemoteDesk: true,
|
|
isRemoteDesk: true,
|
|
|
});
|
|
});
|
|
|
videoWrapRef.value = remoteVideoRef.value;
|
|
videoWrapRef.value = remoteVideoRef.value;
|
|
|
|
|
+ window.addEventListener('keydown', handleKeyDown);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-function handleMoveMouse() {
|
|
|
|
|
- networkStore.wsMap.get(roomId.value)?.send<WsRemoteDeskMoveMsgType['data']>({
|
|
|
|
|
- requestId: getRandomString(8),
|
|
|
|
|
- msgType: WsMsgTypeEnum.remoteDeskMoveMsg,
|
|
|
|
|
- data: {
|
|
|
|
|
- roomId: roomId.value,
|
|
|
|
|
- sender: mySocketId.value,
|
|
|
|
|
- receiver: receiverId.value,
|
|
|
|
|
- },
|
|
|
|
|
- });
|
|
|
|
|
|
|
+function handleKeyDown(e: KeyboardEvent) {
|
|
|
|
|
+ // console.log(e.key, e.code);
|
|
|
|
|
+ const keyMap = {
|
|
|
|
|
+ Enter: Key.Enter,
|
|
|
|
|
+ Space: Key.Space,
|
|
|
|
|
+ Backspace: Key.Backspace,
|
|
|
|
|
+ ShiftLeft: Key.LeftShift,
|
|
|
|
|
+ ShiftRight: Key.RightShift,
|
|
|
|
|
+ AltLeft: Key.LeftAlt,
|
|
|
|
|
+ AltRight: Key.RightAlt,
|
|
|
|
|
+ Tab: Key.Tab,
|
|
|
|
|
+ Backquote: Key.Quote,
|
|
|
|
|
+ Backslash: Key.Backslash,
|
|
|
|
|
+ ArrowUp: Key.Up,
|
|
|
|
|
+ ArrowDown: Key.Down,
|
|
|
|
|
+ ArrowLeft: Key.Left,
|
|
|
|
|
+ ArrowRight: Key.Right,
|
|
|
|
|
+ CapsLock: Key.CapsLock,
|
|
|
|
|
+ ControlLeft: Key.LeftControl,
|
|
|
|
|
+ ControlRight: Key.RightControl,
|
|
|
|
|
+ MetaLeft: Key.LeftCmd,
|
|
|
|
|
+ LeftWin: Key.LeftCmd,
|
|
|
|
|
+ MetaRight: Key.RightCmd,
|
|
|
|
|
+ RightWin: Key.RightCmd,
|
|
|
|
|
+ Fn: Key.Fn,
|
|
|
|
|
+ F1: Key.F1,
|
|
|
|
|
+ F2: Key.F2,
|
|
|
|
|
+ F3: Key.F3,
|
|
|
|
|
+ F4: Key.F4,
|
|
|
|
|
+ F5: Key.F5,
|
|
|
|
|
+ F6: Key.F6,
|
|
|
|
|
+ F7: Key.F7,
|
|
|
|
|
+ F8: Key.F8,
|
|
|
|
|
+ F9: Key.F9,
|
|
|
|
|
+ F10: Key.F10,
|
|
|
|
|
+ F11: Key.F11,
|
|
|
|
|
+ F12: Key.F12,
|
|
|
|
|
+ F13: Key.F13,
|
|
|
|
|
+ F14: Key.F14,
|
|
|
|
|
+ F15: Key.F15,
|
|
|
|
|
+ F16: Key.F16,
|
|
|
|
|
+ F17: Key.F17,
|
|
|
|
|
+ F18: Key.F18,
|
|
|
|
|
+ F19: Key.F19,
|
|
|
|
|
+ F20: Key.F20,
|
|
|
|
|
+ F21: Key.F21,
|
|
|
|
|
+ F22: Key.F22,
|
|
|
|
|
+ F23: Key.F23,
|
|
|
|
|
+ F24: Key.F24,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ networkStore.rtcMap
|
|
|
|
|
+ .get(receiverId.value)
|
|
|
|
|
+ ?.dataChannelSend<WsRemoteDeskBehaviorType['data']>({
|
|
|
|
|
+ requestId: getRandomString(8),
|
|
|
|
|
+ msgType: WsMsgTypeEnum.remoteDeskBehavior,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ roomId: roomId.value,
|
|
|
|
|
+ sender: mySocketId.value,
|
|
|
|
|
+ receiver: receiverId.value,
|
|
|
|
|
+ type: RemoteDeskBehaviorEnum.keyboardType,
|
|
|
|
|
+ keyboardtype: keyMap[e.code] || e.key,
|
|
|
|
|
+ x: 0,
|
|
|
|
|
+ y: 0,
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+watch(
|
|
|
|
|
+ () => appStore.remoteDesk.isClose,
|
|
|
|
|
+ (newval) => {
|
|
|
|
|
+ if (newval) {
|
|
|
|
|
+ useTip({
|
|
|
|
|
+ content: '远程连接断开',
|
|
|
|
|
+ hiddenCancel: true,
|
|
|
|
|
+ hiddenClose: true,
|
|
|
|
|
+ }).catch();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+function handleDoublelclick() {
|
|
|
|
|
+ networkStore.rtcMap
|
|
|
|
|
+ .get(receiverId.value)
|
|
|
|
|
+ ?.dataChannelSend<WsRemoteDeskBehaviorType['data']>({
|
|
|
|
|
+ requestId: getRandomString(8),
|
|
|
|
|
+ msgType: WsMsgTypeEnum.remoteDeskBehavior,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ roomId: roomId.value,
|
|
|
|
|
+ sender: mySocketId.value,
|
|
|
|
|
+ receiver: receiverId.value,
|
|
|
|
|
+ type: RemoteDeskBehaviorEnum.doubleClick,
|
|
|
|
|
+ keyboardtype: 0,
|
|
|
|
|
+ x: 0,
|
|
|
|
|
+ y: 0,
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleContextmenu() {
|
|
|
|
|
+ networkStore.rtcMap
|
|
|
|
|
+ .get(receiverId.value)
|
|
|
|
|
+ ?.dataChannelSend<WsRemoteDeskBehaviorType['data']>({
|
|
|
|
|
+ requestId: getRandomString(8),
|
|
|
|
|
+ msgType: WsMsgTypeEnum.remoteDeskBehavior,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ roomId: roomId.value,
|
|
|
|
|
+ sender: mySocketId.value,
|
|
|
|
|
+ receiver: receiverId.value,
|
|
|
|
|
+ type: RemoteDeskBehaviorEnum.rightClick,
|
|
|
|
|
+ keyboardtype: 0,
|
|
|
|
|
+ x: 0,
|
|
|
|
|
+ y: 0,
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleMouseDown(event: MouseEvent) {
|
|
|
|
|
+ isDown.value = true;
|
|
|
|
|
+ clickTimer = setTimeout(function () {
|
|
|
|
|
+ console.log('长按');
|
|
|
|
|
+ isLongClick = true;
|
|
|
|
|
+ clearTimeout(clickTimer);
|
|
|
|
|
+ }, 300);
|
|
|
|
|
+ // 获取点击相对于视窗的位置
|
|
|
|
|
+ const clickX = event.clientX;
|
|
|
|
|
+ const clickY = event.clientY;
|
|
|
|
|
+
|
|
|
|
|
+ // 获取目标元素的位置和尺寸信息
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ const rect: DOMRect = event.target.getBoundingClientRect();
|
|
|
|
|
+ // 计算点击位置相对于元素的坐标
|
|
|
|
|
+ const xInsideElement = clickX - rect.left;
|
|
|
|
|
+ const yInsideElement = clickY - rect.top;
|
|
|
|
|
+ const x = (xInsideElement / rect.width) * 1000;
|
|
|
|
|
+ const y = (yInsideElement / rect.height) * 1000;
|
|
|
|
|
+ console.log('handleMouseDown', x, y, xInsideElement, yInsideElement);
|
|
|
|
|
+ networkStore.rtcMap
|
|
|
|
|
+ .get(receiverId.value)
|
|
|
|
|
+ ?.dataChannelSend<WsRemoteDeskBehaviorType['data']>({
|
|
|
|
|
+ requestId: getRandomString(8),
|
|
|
|
|
+ msgType: WsMsgTypeEnum.remoteDeskBehavior,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ roomId: roomId.value,
|
|
|
|
|
+ sender: mySocketId.value,
|
|
|
|
|
+ receiver: receiverId.value,
|
|
|
|
|
+ type: isLongClick
|
|
|
|
|
+ ? RemoteDeskBehaviorEnum.pressButtonLeft
|
|
|
|
|
+ : RemoteDeskBehaviorEnum.pressButtonLeft,
|
|
|
|
|
+ x,
|
|
|
|
|
+ y,
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleMouseMove(event: MouseEvent) {
|
|
|
|
|
+ // 获取点击相对于视窗的位置
|
|
|
|
|
+ const clickX = event.clientX;
|
|
|
|
|
+ const clickY = event.clientY;
|
|
|
|
|
+
|
|
|
|
|
+ // 获取目标元素的位置和尺寸信息
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ const rect: DOMRect = event.target.getBoundingClientRect();
|
|
|
|
|
+ // 计算点击位置相对于元素的坐标
|
|
|
|
|
+ const xInsideElement = clickX - rect.left;
|
|
|
|
|
+ const yInsideElement = clickY - rect.top;
|
|
|
|
|
+ const x = (xInsideElement / rect.width) * 1000;
|
|
|
|
|
+ const y = (yInsideElement / rect.height) * 1000;
|
|
|
|
|
+ console.log('handleMouseMove', x, y, xInsideElement, yInsideElement);
|
|
|
|
|
+ networkStore.rtcMap
|
|
|
|
|
+ .get(receiverId.value)
|
|
|
|
|
+ ?.dataChannelSend<WsRemoteDeskBehaviorType['data']>({
|
|
|
|
|
+ requestId: getRandomString(8),
|
|
|
|
|
+ msgType: WsMsgTypeEnum.remoteDeskBehavior,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ roomId: roomId.value,
|
|
|
|
|
+ sender: mySocketId.value,
|
|
|
|
|
+ receiver: receiverId.value,
|
|
|
|
|
+ type: RemoteDeskBehaviorEnum.move,
|
|
|
|
|
+ keyboardtype: 0,
|
|
|
|
|
+ x,
|
|
|
|
|
+ y,
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleMouseUp(event: MouseEvent) {
|
|
|
|
|
+ if (clickTimer) {
|
|
|
|
|
+ clearTimeout(clickTimer);
|
|
|
|
|
+ }
|
|
|
|
|
+ isDown.value = false;
|
|
|
|
|
+ // 获取点击相对于视窗的位置
|
|
|
|
|
+ const clickX = event.clientX;
|
|
|
|
|
+ const clickY = event.clientY;
|
|
|
|
|
+
|
|
|
|
|
+ // 获取目标元素的位置和尺寸信息
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ const rect: DOMRect = event.target.getBoundingClientRect();
|
|
|
|
|
+ // 计算点击位置相对于元素的坐标
|
|
|
|
|
+ const xInsideElement = clickX - rect.left;
|
|
|
|
|
+ const yInsideElement = clickY - rect.top;
|
|
|
|
|
+ const x = (xInsideElement / rect.width) * 1000;
|
|
|
|
|
+ const y = (yInsideElement / rect.height) * 1000;
|
|
|
|
|
+ console.log('handleMouseUp', x, y, xInsideElement, yInsideElement);
|
|
|
|
|
+ networkStore.rtcMap
|
|
|
|
|
+ .get(receiverId.value)
|
|
|
|
|
+ ?.dataChannelSend<WsRemoteDeskBehaviorType['data']>({
|
|
|
|
|
+ requestId: getRandomString(8),
|
|
|
|
|
+ msgType: WsMsgTypeEnum.remoteDeskBehavior,
|
|
|
|
|
+ data: {
|
|
|
|
|
+ roomId: roomId.value,
|
|
|
|
|
+ sender: mySocketId.value,
|
|
|
|
|
+ receiver: receiverId.value,
|
|
|
|
|
+ keyboardtype: '',
|
|
|
|
|
+ type: isLongClick
|
|
|
|
|
+ ? RemoteDeskBehaviorEnum.releaseButtonLeft
|
|
|
|
|
+ : RemoteDeskBehaviorEnum.releaseButtonLeft,
|
|
|
|
|
+ x,
|
|
|
|
|
+ y,
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
|
|
+ isLongClick = false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleClose() {
|
|
|
|
|
+ networkStore.rtcMap.get(receiverId.value)?.close();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function handleRemote() {
|
|
function handleRemote() {
|
|
@@ -88,6 +330,7 @@ function handleRemote() {
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
.wrap {
|
|
.wrap {
|
|
|
- display: inline-block;
|
|
|
|
|
|
|
+ line-height: 0;
|
|
|
|
|
+ cursor: none;
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|