1225 lines
49 KiB
Vue
1225 lines
49 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="device-layout">
|
|||
|
|
<!-- 左侧设备小窗口列表 -->
|
|||
|
|
<div class="device-list">
|
|||
|
|
<div v-for="(device, index) in deviceInformation" :key="device.udid" class="device-mini"
|
|||
|
|
:class="{ active: selectedDevice === index }" @click="selectDevice(index)">
|
|||
|
|
<video :ref="el => (videoElement[device.udid] = el)" autoplay muted playsinline class="mini-video"
|
|||
|
|
:style="{ width: phone.width + 'px', height: phone.height / 2 + 'px' }"></video>
|
|||
|
|
<canvas class="mini-canvas" :ref="el => (canvasRef[device.udid] = el)"
|
|||
|
|
:style="{ width: phone.width + 'px', height: phone.height / 2 + 'px' }"></canvas>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 右侧选中大窗口 -->
|
|||
|
|
<div class="device-main" v-if="currentDevice">
|
|||
|
|
<video :ref="el => (videoElement[currentDevice.udid] = el)" autoplay muted playsinline class="main-video"
|
|||
|
|
:style="{ width: phone.width * 2 + 'px', height: phone.height * 2 + 'px' }"></video>
|
|||
|
|
<canvas class="main-canvas" :ref="el => (canvasRef[currentDevice.udid] = el)"
|
|||
|
|
:style="{ width: phone.width * 2 + 'px', height: phone.height * 2 + 'px' }"
|
|||
|
|
@mousemove.stop="(e) => handleMouseMove(currentDevice.udid, e, selectedDevice)"
|
|||
|
|
@mousedown.stop="(e) => handleCanvasdown(currentDevice.udid, e, selectedDevice)"
|
|||
|
|
@mouseup="(e) => handleCanvasup(currentDevice.udid, e, selectedDevice)"></canvas>
|
|||
|
|
<!-- 右侧所有你原本的按钮、输入框等 -->
|
|||
|
|
<div class="main-controls">
|
|||
|
|
<!-- 全部直接复用你的按钮和输入框。建议用弹窗或右下角固定区,不影响大画面 -->
|
|||
|
|
<!-- 这里直接插入你原来设备面板的按钮/输入栏代码(按需自定义/复用) -->
|
|||
|
|
|
|||
|
|
<el-button class="open" @click="wsActions.open(currentDevice.udid, selectedDevice)"></el-button>
|
|||
|
|
<el-button class="Back" @click="Back(currentDevice.udid, selectedDevice)"></el-button>
|
|||
|
|
<el-button class="Home" @click="Home(currentDevice.udid, selectedDevice)"></el-button>
|
|||
|
|
<el-button class="Overview" @click="Overview(currentDevice.udid, selectedDevice)"></el-button>
|
|||
|
|
<el-button @click="reloadfun()">修复播放</el-button>
|
|||
|
|
<el-button @click="wsActions.clickCopyList(currentDevice.udid, selectedDevice)">私信列表</el-button>
|
|||
|
|
<el-button @click="wsActions.isHost(currentDevice.udid, selectedDevice)">开始养号</el-button>
|
|||
|
|
<el-button @click="openComArr(selectedDevice)">导入评论</el-button>
|
|||
|
|
<el-button @click="getComArr(selectedDevice)">查看评论</el-button>
|
|||
|
|
<el-button @click="wsActions.test(currentDevice.udid, selectedDevice)">截屏</el-button>
|
|||
|
|
<el-button @click="LikesToLikesToLikes(currentDevice.udid, selectedDevice)">批量关注</el-button>
|
|||
|
|
<div style="display: flex;">
|
|||
|
|
<div style="width: 150px;">主播id</div>
|
|||
|
|
<el-input style="border: 1px solid #000;" v-model="hostIdContent[selectedDevice]"
|
|||
|
|
type="text"></el-input>
|
|||
|
|
<el-button @click="setHostId(selectedDevice)">发送</el-button>
|
|||
|
|
</div>
|
|||
|
|
<div style="display: flex;">
|
|||
|
|
<div style="width: 150px;">评论内容:</div>
|
|||
|
|
<el-input style="border: 1px solid #000;" v-model="textContent[selectedDevice]"
|
|||
|
|
type="text"></el-input>
|
|||
|
|
<el-button @click="setComText(selectedDevice)">发送</el-button>
|
|||
|
|
</div>
|
|||
|
|
<el-button @click="clickxy(160, 360, selectedDevice)">开始/暂停</el-button>
|
|||
|
|
<el-button @click="getText(selectedDevice)">获取粘贴板内容</el-button>
|
|||
|
|
<el-button @click="wsActions.isVideoAndLive(currentDevice.udid, selectedDevice)">判断视频还是直播</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref, computed, onMounted, onUnmounted, onBeforeUnmount, watch, inject } from "vue";
|
|||
|
|
// ---- 保持你所有 import 和原有业务逻辑不变 ----
|
|||
|
|
import VideoConverter from "h264-converter";
|
|||
|
|
import { Buffer } from 'buffer';
|
|||
|
|
import { setphoneXYinfo, getphoneXYinfo } from '@/utils/storage'
|
|||
|
|
import { set } from "lodash";
|
|||
|
|
import { toBufferBtn, stringToUtf8ByteArray, getClipboard, setClipboard, bufferToString, startsWithHeader, trimLongArray, base64ToBinary, toBuffer } from '@/utils/bufferUtils';
|
|||
|
|
import { createWsActions } from '@/utils/wsActions';
|
|||
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|||
|
|
import { chat } from "@/api/chat";
|
|||
|
|
|
|||
|
|
// ---- 你的所有原有 setup 代码、ref变量、方法、WebSocket逻辑全保留 ----
|
|||
|
|
let wsActions = null;
|
|||
|
|
const reload = inject("reload")
|
|||
|
|
|
|||
|
|
let phone = ref({ width: 160, height: 360 });
|
|||
|
|
const srt = base64ToBinary("ZQBwAAAAAAA8CgLQAtAAAAAAAAAAAAD/AAAAAAAAAAAAAAAA");
|
|||
|
|
const eitwo = base64ToBinary("BAIAAABHVFJD");
|
|||
|
|
let isshow = ref(true);
|
|||
|
|
let playTimer = ref([{}, {}, {}, {}, {}, {}, {}, {}]);
|
|||
|
|
let isdown = ref(false);
|
|||
|
|
const videoElement = ref({});
|
|||
|
|
let deviceInformation = ref([]);
|
|||
|
|
//评论文本内容
|
|||
|
|
let textContent = ref(['', '', '', '', '', '', '', '']);
|
|||
|
|
let textContentArr = ref([[], [], [], [], [], [], [], [], []]);
|
|||
|
|
//主播id内容
|
|||
|
|
let hostIdContent = ref(['', '', '', '', '', '', '', '']);
|
|||
|
|
let hostIdContentArr = ref([[], [], [], [], [], [], [], [], []]);
|
|||
|
|
let textContentpri = ref(['', '', '', '', '', '', '', '']);
|
|||
|
|
let selectedDevice = ref(0); // 默认选中第一个
|
|||
|
|
let wslist = [];
|
|||
|
|
let isStopLike = ref([false, false, false, false, false, false, false, false]);
|
|||
|
|
let instanceList = ref([{}, {}, {}, {}, {}, {}, {}, {}]);
|
|||
|
|
let isHostInfo = ref([false, false, false, false, false, false, false, false]);
|
|||
|
|
let iponeCoefficient = ref([{ width: 1, height: 1 }, { width: 1, height: 1 }, { width: 1, height: 1 }, { width: 1, height: 1 }, { width: 1, height: 1 }, { width: 1, height: 1 }, { width: 1, height: 1 }, { width: 1, height: 1 }]);
|
|||
|
|
let isSend = ref(false)
|
|||
|
|
const taskQueues = new Map();
|
|||
|
|
|
|||
|
|
const mouseData = {
|
|||
|
|
type: 2,
|
|||
|
|
action: 0,
|
|||
|
|
pointerId: 0,
|
|||
|
|
position: {
|
|||
|
|
point: { x: 0, y: 0 },
|
|||
|
|
screenSize: { width: 320, height: 720 },
|
|||
|
|
},
|
|||
|
|
pressure: 1,
|
|||
|
|
buttons: 1,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let phoneXYinfo = ref(getphoneXYinfo() == null ? [{}, {}, {}, {}, {}, {}, {}, {}] : getphoneXYinfo());
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 选中设备信息
|
|||
|
|
const currentDevice = computed(() => deviceInformation.value[selectedDevice.value] || null);
|
|||
|
|
|
|||
|
|
// 选中事件
|
|||
|
|
function selectDevice(index) {
|
|||
|
|
selectedDevice.value = index;
|
|||
|
|
}
|
|||
|
|
const wsCache = new Map();
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
// 初始化 手机显示WebSocket 和视频流
|
|||
|
|
const initVideoStream = (udid, index) => {
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
// 1. 检查缓存中是否已有实例
|
|||
|
|
if (wsCache.has(udid)) {
|
|||
|
|
const cachedWs = wsCache.get(udid);
|
|||
|
|
if (cachedWs.readyState === WebSocket.OPEN) {
|
|||
|
|
return cachedWs;
|
|||
|
|
}
|
|||
|
|
// 如果连接已关闭,清除缓存并重新创建
|
|||
|
|
wsCache.delete(udid);
|
|||
|
|
}
|
|||
|
|
// 2. 创建专用实例容器
|
|||
|
|
instanceList.value[index] = {
|
|||
|
|
wsVideo: null,
|
|||
|
|
converter: null,
|
|||
|
|
timer: null
|
|||
|
|
};
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
if (!videoElement.value) return;
|
|||
|
|
// 1. 创建 h264-converter 实例
|
|||
|
|
instanceList.value[index].converter = new VideoConverter(videoElement.value[udid], 60, 1);
|
|||
|
|
// instanceList.value[index].converter.play();
|
|||
|
|
// 2. 连接 WebSocket
|
|||
|
|
wslist[index] = new WebSocket(
|
|||
|
|
`ws://127.0.0.1:8000/?action=proxy-adb&remote=tcp%3A8886&udid=${udid}`
|
|||
|
|
);
|
|||
|
|
wslist[index].binaryType = "arraybuffer";
|
|||
|
|
wslist[index].onopen = () => {
|
|||
|
|
console.log("手机显示ws已开启");
|
|||
|
|
|
|||
|
|
wsActions = createWsActions(wslist, isStopLike);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 发送 开启 视频流数据
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wslist[index].send(srt);
|
|||
|
|
}, 300);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// console.log('playTimer.value[index]', playTimer.value)
|
|||
|
|
playTimer.value[index] = setTimeout(() => {
|
|||
|
|
// console.log('第' + index + '台设备开始播放', instanceList.value[index].converter)
|
|||
|
|
// console.log("udid", udid);
|
|||
|
|
instanceList.value[index].converter.play();
|
|||
|
|
}, 3000);
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
wsCache.set(udid, instanceList.value[index]);
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
};
|
|||
|
|
const magicSize = stringToUtf8ByteArray('scrcpy_message');
|
|||
|
|
|
|||
|
|
// 3. 处理接收到的二进制数据
|
|||
|
|
wslist[index].onmessage = (event) => {
|
|||
|
|
const data = new Uint8Array(event.data);
|
|||
|
|
|
|||
|
|
|
|||
|
|
//判断返回的如果是字符串为自定义返回
|
|||
|
|
if (typeof event.data == 'string') {
|
|||
|
|
const resData = JSON.parse(event.data)
|
|||
|
|
//成功处理
|
|||
|
|
console.log('自定义返回', resData)
|
|||
|
|
if (resData.status === 'success') {
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (resData.type == 'PrivatePush') {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// clickxy(160, 360, index)
|
|||
|
|
// LikesToCommentToComPush(deviceInformation.value[index].udid, index) //是否继续循环任务
|
|||
|
|
// }, generateRandomNumber());
|
|||
|
|
// }, 1000);
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}, 1000);
|
|||
|
|
|
|||
|
|
}, 1000);
|
|||
|
|
|
|||
|
|
}, 1000);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//触发长按该位置
|
|||
|
|
if (resData.type == 'clickCopy') {
|
|||
|
|
console.log('长按', resData.x * iponeCoefficient.value[index].width, resData.y * iponeCoefficient.value[index].height, index)
|
|||
|
|
clickxy(resData.x * iponeCoefficient.value[index].width, resData.y * iponeCoefficient.value[index].height, index, 9) //index为9的时候长按
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wsActions.clickCopyText(resData.udid, index)
|
|||
|
|
}, 1500);
|
|||
|
|
} else if (resData.type == 'getmesNum') {
|
|||
|
|
if (resData.message == 0) {
|
|||
|
|
console.log('没有消息')
|
|||
|
|
} else if (resData.message == 1) {
|
|||
|
|
console.log('有消息')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
} else if (resData.type == 'isVideoAndLive') {
|
|||
|
|
console.log(resData.message)
|
|||
|
|
|
|||
|
|
} else if (resData.type == 'clickCopyList') { //获取到的消息列表
|
|||
|
|
console.log(resData.message)
|
|||
|
|
const mesBox = resData.message[resData.message.length - 1]
|
|||
|
|
console.log(mesBox)
|
|||
|
|
chat({ messages: [{ role: "user", content: mesBox.text }] }).then(res => {
|
|||
|
|
console.log(res)
|
|||
|
|
})
|
|||
|
|
} else if (resData.action == 'getSize') {
|
|||
|
|
console.log(iponeCoefficient.value, '手机尺寸宽度:', resData.width, '高度:', resData.height);
|
|||
|
|
iponeCoefficient.value[index].width = phone.value.width / resData.width
|
|||
|
|
iponeCoefficient.value[index].height = phone.value.height / resData.height
|
|||
|
|
|
|||
|
|
console.log('尺寸系数', iponeCoefficient.value[index])
|
|||
|
|
} else {
|
|||
|
|
console.log(resData.type, '坐标返回:x:', resData.x, 'y:', resData.y);
|
|||
|
|
// clickxy(resData.x * 0.3, resData.y * 0.3, index)
|
|||
|
|
}
|
|||
|
|
phoneXYinfo.value[index].id = resData.udid
|
|||
|
|
if (resData.type == 'Likes') {//判断是否是 点赞
|
|||
|
|
phoneXYinfo.value[index].Likes = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
if (isHostInfo.value[index]) {
|
|||
|
|
wsActions.slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
|||
|
|
}
|
|||
|
|
} else if (resData.type == 'Comment') {//打开评论
|
|||
|
|
phoneXYinfo.value[index].Comment = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
} else if (resData.type == 'Comtext') {//评论输入
|
|||
|
|
phoneXYinfo.value[index].Comtext = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// setComText(index)//粘贴内容
|
|||
|
|
// }, 1000)
|
|||
|
|
} else if (resData.type == 'ComPush') {//评论发送
|
|||
|
|
phoneXYinfo.value[index].ComPush = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
if (isHostInfo.value[index]) {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
}, 1000)
|
|||
|
|
} else {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wsActions.slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
|||
|
|
setTimeout(() => {
|
|||
|
|
console.log('观看视频中')
|
|||
|
|
randomSeeVideo(deviceInformation.value[index].udid, index) //50秒后继续循环任务
|
|||
|
|
}, 1000);
|
|||
|
|
}, 1000)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}, 800)
|
|||
|
|
} else if (resData.type == 'tomy') {//打开主页
|
|||
|
|
phoneXYinfo.value[index].tomy = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
} else if (resData.type == 'Attention') {//关注、打开私信
|
|||
|
|
phoneXYinfo.value[index].Attention = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
// LikesToCommentToComPush(deviceInformation.value[index].udid, index) //是否继续循环任务
|
|||
|
|
} else if (resData.type == 'return') {//私信评论
|
|||
|
|
phoneXYinfo.value[index].return = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
// wsActions.slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// LikesToCommentToComPush(deviceInformation.value[index].udid, index)
|
|||
|
|
// }, 1000);
|
|||
|
|
} else if (resData.type == 'addHost') {//添加关注
|
|||
|
|
phoneXYinfo.value[index].addHost = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
wsActions.slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wsActions.isHost(deviceInformation.value[index].udid, index)//检测
|
|||
|
|
}, 1000);
|
|||
|
|
} else if (resData.type == 'Privatetex') {//私信评论
|
|||
|
|
phoneXYinfo.value[index].Privatetex = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
} else if (resData.type == 'PrivatePush') {//私信发送
|
|||
|
|
phoneXYinfo.value[index].PrivatePush = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
if (isHostInfo.value[index]) {
|
|||
|
|
isHostInfo.value[index] = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
} else if (resData.type == 'clickCopy') {//点击复制
|
|||
|
|
phoneXYinfo.value[index].clickCopy = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
} else if (resData.type == 'hostVideo') {//点击复制
|
|||
|
|
phoneXYinfo.value[index].hostVideo = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
|
|||
|
|
} else if (resData.type == 'isHost') {//视频关注主播
|
|||
|
|
phoneXYinfo.value[index].isHost = { x: resData.x * iponeCoefficient.value[index].width, y: resData.y * iponeCoefficient.value[index].height }
|
|||
|
|
|
|||
|
|
if (resData.message == 0) {
|
|||
|
|
console.log('无关注')
|
|||
|
|
Back(deviceInformation.value[index].udid, index)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
|
|||
|
|
console.log('观看视频中')
|
|||
|
|
randomSeeVideo(deviceInformation.value[index].udid, index) //30-50秒后继续循环任务
|
|||
|
|
}, 1000);
|
|||
|
|
} else if (resData.message == 1) {
|
|||
|
|
console.log('有关注')
|
|||
|
|
const randomNum = Math.random(); // 生成一个0到1之间的随机数
|
|||
|
|
if (randomNum < 0.5) {
|
|||
|
|
console.log('进行点赞评论')
|
|||
|
|
LikesToCommentToComPush(deviceInformation.value[index].udid, index)
|
|||
|
|
} else {
|
|||
|
|
console.log('下一个')
|
|||
|
|
wsActions.slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
|||
|
|
setTimeout(() => {
|
|||
|
|
console.log('观看视频中')
|
|||
|
|
randomSeeVideo(deviceInformation.value[index].udid, index) //30-50秒后继续循环任务
|
|||
|
|
}, 1000);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
setphoneXYinfo(phoneXYinfo.value)
|
|||
|
|
if (resData.type != 'isHost') {
|
|||
|
|
|
|||
|
|
if (resData.type == 'hostVideo' || resData.type == 'Likes') {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
createTaskQueue(index).next(); // 继续队列中下一个任务
|
|||
|
|
}, 5000)
|
|||
|
|
} else {
|
|||
|
|
createTaskQueue(index).next(); // 继续队列中下一个任务
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
console.error(resData.type, resData)
|
|||
|
|
if (resData.type == 'Comtext') {
|
|||
|
|
createTaskQueue(index).clear();//清除队伍中的任务
|
|||
|
|
Back('', index)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wsActions.isHost(deviceInformation.value[index].udid, index)
|
|||
|
|
|
|||
|
|
}, 1000)
|
|||
|
|
}, 1000)
|
|||
|
|
} else {
|
|||
|
|
console.error(resData.message); // 错误处理
|
|||
|
|
ElMessage.error(resData.message);
|
|||
|
|
createTaskQueue(index).clear();//清除队伍中的任务
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// createTaskQueue(index).next(); // 继续队列中下一个任务
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//返回粘贴板内容
|
|||
|
|
if (startsWithHeader(magicSize, data)) {
|
|||
|
|
if (!isSend.value) {
|
|||
|
|
const buffer = trimLongArray(data, magicSize);
|
|||
|
|
const paste = bufferToString(buffer);
|
|||
|
|
console.log('获取粘贴板内容', paste)
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//视频流处理
|
|||
|
|
if (instanceList.value[index].converter) {
|
|||
|
|
if (isshow.value) {
|
|||
|
|
instanceList.value[index].converter.appendRawData(data);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
// 4. 错误处理
|
|||
|
|
wslist[index].onerror = (error) => {
|
|||
|
|
wsCache.delete(udid); // 错误时清理缓存
|
|||
|
|
};
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
wslist[index].onclose = (event) => {
|
|||
|
|
wsCache.delete(udid)// 自动清理缓存
|
|||
|
|
clearInterval(instanceList.value[index].timer); // 清理定时器// 移除缓存
|
|||
|
|
};
|
|||
|
|
//``````````````````````````````````````````````````````````````````````````````````
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 配置参数
|
|||
|
|
let canvasRef = ref({});
|
|||
|
|
|
|||
|
|
// 初始化画布
|
|||
|
|
const initCanvas = (udid) => {
|
|||
|
|
const canvas = canvasRef.value[udid];
|
|||
|
|
const dpr = window.devicePixelRatio || 1;
|
|||
|
|
|
|||
|
|
canvas.style.width = `${phone.value.width * 2}px`;
|
|||
|
|
canvas.style.height = `${phone.value.height * 2}px`;
|
|||
|
|
canvas.width = phone.value.width * 2 * dpr;
|
|||
|
|
canvas.height = phone.value.height * 2 * dpr;
|
|||
|
|
|
|||
|
|
const ctx = canvas.getContext("2d");
|
|||
|
|
ctx.scale(dpr, dpr);
|
|||
|
|
|
|||
|
|
// 绘制参考网格(可选)
|
|||
|
|
ctx.strokeStyle = "#ffffff00";
|
|||
|
|
for (let x = 0; x <= phone.value.width; x += 100) {
|
|||
|
|
ctx.beginPath();
|
|||
|
|
ctx.moveTo(x, 0);
|
|||
|
|
ctx.lineTo(x, phone.value.height);
|
|||
|
|
ctx.stroke();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 鼠标按下事件处理
|
|||
|
|
const handleCanvasdown = (udid, event, index) => {
|
|||
|
|
const { x, y } = getCanvasCoordinate(event, udid);
|
|||
|
|
console.log("鼠标按下", x, y);
|
|||
|
|
isdown.value = true;
|
|||
|
|
mouseData.action = 0;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
// console.log(mouseData);
|
|||
|
|
console.log(index)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
selectedDevice.value = index;
|
|||
|
|
}, 300);
|
|||
|
|
console.log(wslist)
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 鼠标抬起事件处理
|
|||
|
|
const handleCanvasup = (udid, event, index) => {
|
|||
|
|
const { x, y } = getCanvasCoordinate(event, udid);
|
|||
|
|
// position.endX = floorNum(x)
|
|||
|
|
// position.endY = floorNum(y)
|
|||
|
|
isdown.value = false;
|
|||
|
|
mouseData.action = 1;
|
|||
|
|
mouseData.pressure = 0;
|
|||
|
|
mouseData.buttons = 0;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
// console.log(mouseData);
|
|||
|
|
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 鼠标移动事件处理
|
|||
|
|
const handleMouseMove = (udid, event, index) => {
|
|||
|
|
if (isdown.value) {
|
|||
|
|
const { x, y } = getCanvasCoordinate(event, udid);
|
|||
|
|
// position.startX = floorNum(x)
|
|||
|
|
// position.startY = floorNum(y)
|
|||
|
|
mouseData.action = 2;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
// console.log(mouseData);
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 坐标计算
|
|||
|
|
const getCanvasCoordinate = (event, udid) => {
|
|||
|
|
const canvas = canvasRef.value[udid];
|
|||
|
|
const rect = canvas.getBoundingClientRect();
|
|||
|
|
const dpr = window.devicePixelRatio || 1;
|
|||
|
|
return {
|
|||
|
|
x: (event.clientX - rect.left) * dpr,
|
|||
|
|
y: (event.clientY - rect.top) * dpr,
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
//返回上一层
|
|||
|
|
const Back = (udid, index) => {
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 0, "keycode": 4, "metaState": 0, "repeat": 0 }));
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 1, "keycode": 4, "metaState": 0, "repeat": 0 }));
|
|||
|
|
}
|
|||
|
|
//返回首页
|
|||
|
|
const Home = (udid, index) => {
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 0, "keycode": 3, "metaState": 0, "repeat": 0 }));
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 1, "keycode": 3, "metaState": 0, "repeat": 0 }));
|
|||
|
|
}
|
|||
|
|
//任务视图
|
|||
|
|
const Overview = (udid, index) => {
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 0, "keycode": 187, "metaState": 0, "repeat": 0 }));
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 1, "keycode": 187, "metaState": 0, "repeat": 0 }));
|
|||
|
|
}
|
|||
|
|
//回车 index手机下标 state up按下 down抬起 keycode 键
|
|||
|
|
const key = (index, state, keycode) => {
|
|||
|
|
// console.log("退格", index)
|
|||
|
|
if (index === 999) {
|
|||
|
|
return
|
|||
|
|
} else {
|
|||
|
|
if (state == 'up') {
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 1, "keycode": keycode, "metaState": 0, "repeat": 0 }));
|
|||
|
|
} else if (state == 'down') {
|
|||
|
|
wslist[index].send(toBufferBtn({ "type": 0, "action": 0, "keycode": keycode, "metaState": 0, "repeat": 0 }));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const handleVisibilityChange = () => {
|
|||
|
|
if (document.visibilityState === "hidden") {
|
|||
|
|
if (playTimer.value) {
|
|||
|
|
console.log("清除定时器");
|
|||
|
|
playTimer.value.forEach(Timer => {
|
|||
|
|
clearInterval(Timer);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
playTimer.value = [{}, {}, {}, {}, {}, {}, {}, {}];
|
|||
|
|
}
|
|||
|
|
console.log("页面被隐藏");
|
|||
|
|
isshow.value = false;
|
|||
|
|
// 页面被隐藏时执行的逻辑
|
|||
|
|
} else if (document.visibilityState === "visible") {
|
|||
|
|
console.log("页面变为可见");
|
|||
|
|
setTimeout(() => {
|
|||
|
|
isshow.value = true;
|
|||
|
|
}, 500);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
onMounted(() => {
|
|||
|
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|||
|
|
ObtainDeviceInformation();
|
|||
|
|
|
|||
|
|
window.addEventListener('keydown', (e) => {
|
|||
|
|
console.log('触发按键了 键盘事件有效', e)
|
|||
|
|
if (e.key == 'Backspace') {
|
|||
|
|
key(selectedDevice.value, 'down', 67)
|
|||
|
|
} else if (e.keyCode == 17) {
|
|||
|
|
key(selectedDevice.value, 'down', 113)
|
|||
|
|
} else if (e.keyCode == 65) {
|
|||
|
|
key(selectedDevice.value, 'down', 29)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
window.addEventListener('keyup', (e) => {
|
|||
|
|
console.log('触发按键了 键盘事件有效抬起', e.keyCode, e.key)
|
|||
|
|
if (e.key == 'Backspace') {
|
|||
|
|
key(selectedDevice.value, 'up', 67)
|
|||
|
|
} else if (e.keyCode == 17) {
|
|||
|
|
key(selectedDevice.value, 'up', 113)
|
|||
|
|
} else if (e.keyCode == 65) {
|
|||
|
|
key(selectedDevice.value, 'up', 29)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
onBeforeUnmount(() => {
|
|||
|
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 组件卸载时清理
|
|||
|
|
onUnmounted(() => {
|
|||
|
|
console.log("卸载组件");
|
|||
|
|
// if (wsVideo) {
|
|||
|
|
// wsVideo.close();
|
|||
|
|
// }
|
|||
|
|
// if (converter) {
|
|||
|
|
// converter.pause();
|
|||
|
|
// }
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
//获取设备信息
|
|||
|
|
const ObtainDeviceInformation = () => {
|
|||
|
|
// 2. 连接 WebSocket
|
|||
|
|
const ws = new WebSocket("ws://127.0.0.1:8000/?action=multiplex");
|
|||
|
|
ws.binaryType = "arraybuffer";
|
|||
|
|
ws.onopen = () => {
|
|||
|
|
ws.send(eitwo);
|
|||
|
|
};
|
|||
|
|
// 3. 处理接收到的二进制数据
|
|||
|
|
ws.onmessage = (event) => {
|
|||
|
|
const data = JSON.parse(new TextDecoder('utf-8').decode(event.data).replace(/[^\x20-\x7F]/g, ''));
|
|||
|
|
try {
|
|||
|
|
console.log('数组', data)
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (data.type == "devicelist") {
|
|||
|
|
const filteredList = data.data.list.filter(item => item.state === 'device');
|
|||
|
|
//检测到设备列表时,渲染所有设备
|
|||
|
|
filteredList.forEach((item, index) => {
|
|||
|
|
console.log(item);
|
|||
|
|
|
|||
|
|
if (item.state === "device") {
|
|||
|
|
deviceInformation.value.push(item);
|
|||
|
|
console.log("deviceInformation", deviceInformation.value);
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
initVideoStream(item.udid, index);
|
|||
|
|
initCanvas(item.udid);
|
|||
|
|
}, 300);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
} else if (data.type == "device") {
|
|||
|
|
if (data.data.device.state === "offline") {
|
|||
|
|
//监听设备信息,出现离线设备,则删除设备信息
|
|||
|
|
deviceInformation.value.forEach((item, index) => {
|
|||
|
|
if (item.udid === data.data.device.udid) {
|
|||
|
|
deviceInformation.value.splice(index, 1);
|
|||
|
|
if (index < wslist.length - 1) {
|
|||
|
|
deviceInformation.value.forEach((item, index1) => {
|
|||
|
|
//关闭websocket连接
|
|||
|
|
wslist.forEach((item, index) => {
|
|||
|
|
item.close();
|
|||
|
|
})
|
|||
|
|
//重新连接websocket
|
|||
|
|
new Promise((resolve, reject) => {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
try {
|
|||
|
|
initVideoStream(item.udid, index1);
|
|||
|
|
initCanvas(item.udid);
|
|||
|
|
} catch (error) {
|
|||
|
|
reject(error);
|
|||
|
|
}
|
|||
|
|
}, 300);
|
|||
|
|
});
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
console.log("deviceInformation", deviceInformation.value);
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
} else if (data.data.device.state === "device") {
|
|||
|
|
|
|||
|
|
let isrepeat = false;
|
|||
|
|
//监听设备信息,出现新设备,则添加设备信息
|
|||
|
|
deviceInformation.value.forEach((item, index) => {
|
|||
|
|
if (item.udid == data.data.device.udid) {
|
|||
|
|
isrepeat = true;
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if (!isrepeat) {
|
|||
|
|
deviceInformation.value.push(data.data.device);
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// initVideoStream(data.data.device.udid, deviceInformation.value.length - 1);
|
|||
|
|
// initCanvas(data.data.device.udid);
|
|||
|
|
// }, 300);
|
|||
|
|
|
|||
|
|
new Promise((resolve, reject) => {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
try {
|
|||
|
|
initVideoStream(data.data.device.udid, deviceInformation.value.length - 1);
|
|||
|
|
initCanvas(data.data.device.udid);
|
|||
|
|
} catch (error) {
|
|||
|
|
// reject(error);
|
|||
|
|
}
|
|||
|
|
}, 1000);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//喜欢-输入评论
|
|||
|
|
async function LikesToCommentToComPush(udid, index) {
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'isHost', index, resourceId: 'com.zhiliaoapp.musically:id/fug' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Likes', index, resourceId: 'com.zhiliaoapp.musically:id/dy6' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Comment', index, resourceId: 'com.zhiliaoapp.musically:id/cvd' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Comtext', index, resourceId: 'com.zhiliaoapp.musically:id/cs0' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'ComPush', index, resourceId: 'com.zhiliaoapp.musically:id/bqg' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'addHost', index, resourceId: 'com.zhiliaoapp.musically:id/fug' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'tomy', index, resourceId: 'com.zhiliaoapp.musically:id/ts9' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'Attention', index, resourceId: 'com.zhiliaoapp.musically:id/dhx' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'return', index, resourceId: 'com.zhiliaoapp.musically:id/ksm' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'Attention', index, resourceId: 'com.zhiliaoapp.musically:id/dhx' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'Privatetex', index, resourceId: 'com.zhiliaoapp.musically:id/hob' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'PrivatePush', index, resourceId: 'com.zhiliaoapp.musically:id/hog' });
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//点赞主页4个作品+评论最后一个作品并返回
|
|||
|
|
async function LikesToLikesToLikes(udid, index) {
|
|||
|
|
isHostInfo.value[index] = true;
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'search', index, resourceId: 'com.zhiliaoapp.musically:id/gtz' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'searchHost', index, resourceId: 'com.zhiliaoapp.musically:id/t6f' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'toHost', index, resourceId: 'com.zhiliaoapp.musically:id/iso' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'hostVideo', index, resourceId: 'com.zhiliaoapp.musically:id/u3o', num: 0 });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Likes', index, resourceId: 'com.zhiliaoapp.musically:id/dy6' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Likes', index, resourceId: 'com.zhiliaoapp.musically:id/dy6' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Likes', index, resourceId: 'com.zhiliaoapp.musically:id/dy6' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Likes', index, resourceId: 'com.zhiliaoapp.musically:id/dy6' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Comment', index, resourceId: 'com.zhiliaoapp.musically:id/cvd' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Comtext', index, resourceId: 'com.zhiliaoapp.musically:id/cs0' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'ComPush', index, resourceId: 'com.zhiliaoapp.musically:id/bqg' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Attention', index, resourceId: 'com.zhiliaoapp.musically:id/dhx' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Attention', index, resourceId: 'com.zhiliaoapp.musically:id/dhx' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'Privatetex', index, resourceId: 'com.zhiliaoapp.musically:id/hob' });
|
|||
|
|
await sendWsTask(index, { udid, action: 'click', type: 'PrivatePush', index, resourceId: 'com.zhiliaoapp.musically:id/hog' });
|
|||
|
|
// await sendWsTask(index, { udid, action: 'click', type: 'fanhui', index, resourceId: 'com.zhiliaoapp.musically:id/awi' });
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//修复播放
|
|||
|
|
function repair(udid, index) {
|
|||
|
|
console.log(index, instanceList.value[index])
|
|||
|
|
instanceList.value[index].converter.play();
|
|||
|
|
// wslist[index].send(JSON.stringify({ udid: udid, action: 'click', type: 'wait', index: index, resourceId: 'com.zhiliaoapp.musically:id/fcm' }));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//发送私信字符到手机方法
|
|||
|
|
function setComText(index) {
|
|||
|
|
isSend.value = true;
|
|||
|
|
setTimeout(() => {
|
|||
|
|
isSend.value = false;
|
|||
|
|
|
|||
|
|
}, 300);
|
|||
|
|
console.log('发送内容', textContent.value[index])
|
|||
|
|
wslist[index].send(setClipboard(textContent.value[index]));
|
|||
|
|
textContent.value[index] = textContentArr.value[index][getRandomNumber(textContentArr.value[index].length - 1)];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//发送私信字符到手机方法
|
|||
|
|
function setHostId(index) {
|
|||
|
|
isSend.value = true;
|
|||
|
|
setTimeout(() => {
|
|||
|
|
isSend.value = false;
|
|||
|
|
|
|||
|
|
}, 300);
|
|||
|
|
console.log('发送内容', hostIdContent.value[index])
|
|||
|
|
wslist[index].send(setClipboard(hostIdContent.value[index]));
|
|||
|
|
hostIdContent.value[index] = hostIdContentArr.value[index][getRandomNumber(hostIdContentArr.value[index].length - 1)];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//发送评论字符到手机方法
|
|||
|
|
function setPrivateText(index) {
|
|||
|
|
isSend.value = true;
|
|||
|
|
setTimeout(() => {
|
|||
|
|
isSend.value = false;
|
|||
|
|
|
|||
|
|
}, 300);
|
|||
|
|
wslist[index].send(setClipboard(textContentpri.value[index]));
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//获取手机粘贴板方法
|
|||
|
|
function getText(index) {
|
|||
|
|
wslist[index].send(getClipboard());
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function openComArr(index) {
|
|||
|
|
ElMessageBox.prompt('请输入需要评论的内容以英文分号“;”隔开', '评论', {
|
|||
|
|
confirmButtonText: 'OK',
|
|||
|
|
cancelButtonText: '取消',
|
|||
|
|
})
|
|||
|
|
.then(({ value }) => {
|
|||
|
|
var result = value.split(';');
|
|||
|
|
console.log(result)
|
|||
|
|
textContentArr.value[index] = result;
|
|||
|
|
textContent.value[index] = result[0];
|
|||
|
|
})
|
|||
|
|
.catch(() => {
|
|||
|
|
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function getComArr(index) {
|
|||
|
|
ElMessageBox.alert(textContentArr.value[index], '当前评论内容', {
|
|||
|
|
// if you want to disable its autofocus
|
|||
|
|
// autofocus: false,
|
|||
|
|
confirmButtonText: 'OK',
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//传入xy坐标 进行点击
|
|||
|
|
function clickxy(x, y, index, type) {
|
|||
|
|
if (type == 3) { //关注/私信 后的返回和下滑
|
|||
|
|
|
|||
|
|
mouseData.action = 0;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
setTimeout(() => {
|
|||
|
|
mouseData.action = 1;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
}, 100)
|
|||
|
|
//返回和下滑
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wsActions.slideDown(phoneXYinfo.value[index].id, index)
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
start(phoneXYinfo.value[index].id, index)
|
|||
|
|
}, 300)
|
|||
|
|
}, 300)
|
|||
|
|
}, 300)
|
|||
|
|
} else if (type == 2) { //评论过后的返回和右滑
|
|||
|
|
|
|||
|
|
mouseData.action = 0;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
setTimeout(() => {
|
|||
|
|
mouseData.action = 1;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
}, 100)
|
|||
|
|
//返回和右滑
|
|||
|
|
setTimeout(() => {
|
|||
|
|
Back('', index)
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wsActions.slideRight(phoneXYinfo.value[index].id, index)
|
|||
|
|
}, 300)
|
|||
|
|
}, 300)
|
|||
|
|
} else if (type == 1) {//评论框点击后的发送内容
|
|||
|
|
|
|||
|
|
mouseData.action = 0;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
setTimeout(() => {
|
|||
|
|
mouseData.action = 1;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
}, 100)
|
|||
|
|
//发送内容
|
|||
|
|
setTimeout(() => {
|
|||
|
|
console.log('点击了')
|
|||
|
|
setComText(index)
|
|||
|
|
}, 300)
|
|||
|
|
} else if (type == 9) { //长按
|
|||
|
|
mouseData.action = 0;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
console.log('鼠标按下')
|
|||
|
|
setTimeout(() => {
|
|||
|
|
mouseData.action = 1;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
console.log('抬起按下')
|
|||
|
|
|
|||
|
|
}, 1500)
|
|||
|
|
} else {
|
|||
|
|
mouseData.action = 0;
|
|||
|
|
mouseData.pressure = 1;
|
|||
|
|
mouseData.buttons = 1;
|
|||
|
|
mouseData.position.point.x = x;
|
|||
|
|
mouseData.position.point.y = y;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
setTimeout(() => {
|
|||
|
|
mouseData.action = 1;
|
|||
|
|
wslist[index].send(toBuffer(mouseData));
|
|||
|
|
}, 100)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//创建任务实例
|
|||
|
|
function createTaskQueue(index) {
|
|||
|
|
if (!taskQueues.has(index)) {
|
|||
|
|
taskQueues.set(index, []);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
enqueue(task) {
|
|||
|
|
taskQueues.get(index).push(task);
|
|||
|
|
if (taskQueues.get(index).length === 1) {
|
|||
|
|
task(); // 执行第一个任务
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
next() {
|
|||
|
|
const queue = taskQueues.get(index);
|
|||
|
|
queue.shift(); // 移除已完成任务
|
|||
|
|
if (queue.length > 0) {
|
|||
|
|
queue[0](); // 执行下一个任务
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
clear() {
|
|||
|
|
taskQueues.set(index, []); // 清除所有任务
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//发送检查该手机的xy坐标任务
|
|||
|
|
function sendWsTask(index, data) {
|
|||
|
|
console.log('发送任务', data.type);
|
|||
|
|
return new Promise((resolve) => {
|
|||
|
|
const queue = createTaskQueue(index);
|
|||
|
|
|
|||
|
|
const task = () => {
|
|||
|
|
//发送评论的文本粘贴事件
|
|||
|
|
if (data.type == 'Likes') {
|
|||
|
|
clickxy(160, 360, index)
|
|||
|
|
}
|
|||
|
|
if (data.type == 'isHost') {
|
|||
|
|
// clickxy(160, 360, index)
|
|||
|
|
}
|
|||
|
|
if (data.type == 'Comment') {
|
|||
|
|
if (isHostInfo.value[index]) {
|
|||
|
|
clickxy(160, 360, index)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
if (data.type == 'ComPush') {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
setComText(index)//粘贴内容
|
|||
|
|
}, 500)
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
if (data.type == 'searchHost') {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
setHostId(index)//粘贴内容
|
|||
|
|
}, 500)
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//发送私信的文本粘贴事件
|
|||
|
|
if (data.type == 'PrivatePush') {
|
|||
|
|
setPrivateText(index)
|
|||
|
|
}
|
|||
|
|
//关注前的返回和右滑
|
|||
|
|
if (data.type == 'Attention') {
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// Back('', index)
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// wsActions.slideRight(data.udid, index)
|
|||
|
|
// }, 500);
|
|||
|
|
// }, 500);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
//发送关注之前的返回
|
|||
|
|
if (data.type == 'addHost') {
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// Back('', index)
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// clickxy(160, 360, index)
|
|||
|
|
// wsActions.isHost(data.udid, index)
|
|||
|
|
// }, 1000);
|
|||
|
|
// }, 500);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//发送任务
|
|||
|
|
console.log('发送任务', data);
|
|||
|
|
if (data.type == 'Attention') {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
wslist[index].send(JSON.stringify(data));
|
|||
|
|
resolve();
|
|||
|
|
}, 1000)
|
|||
|
|
} else {
|
|||
|
|
wslist[index].send(JSON.stringify(data));
|
|||
|
|
resolve();
|
|||
|
|
}
|
|||
|
|
// 表示当前任务“已发出”,但不是“已完成”
|
|||
|
|
// 实际完成由 onmessage 中的 success 决定并继续执行队列
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
queue.enqueue(task);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
//发送点赞评论任务
|
|||
|
|
function hostInfoFun(udid, index) {
|
|||
|
|
LikesToCommentToComPush(udid, index);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
function getRandomNumber(n) {
|
|||
|
|
return Math.floor(Math.random() * (n + 1));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//延迟30-50秒后检测关注
|
|||
|
|
function randomSeeVideo(udid, index) {
|
|||
|
|
const delay = Math.floor(Math.random() * (50 - 30 + 1) + 30) * 1000;
|
|||
|
|
setTimeout(() => {
|
|||
|
|
console.log('观看结束');
|
|||
|
|
wsActions.isHost(udid, index)//检测
|
|||
|
|
|
|||
|
|
}, delay);
|
|||
|
|
}
|
|||
|
|
// 定义要依次执行的操作
|
|||
|
|
// let actions = [[
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ], [
|
|||
|
|
// (info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
// (info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
// (info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
// (info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
// ]];
|
|||
|
|
|
|||
|
|
|
|||
|
|
//执行已经记录后的xy坐标任务
|
|||
|
|
function performActionsSequentially(actions, index) {
|
|||
|
|
console.log('开始执行', actions, index)
|
|||
|
|
if (actions.length === 0) {
|
|||
|
|
return Promise.resolve();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const action = actions.shift();
|
|||
|
|
if (isStopLike.value[index]) {
|
|||
|
|
console.log('停止执行', actions)
|
|||
|
|
actions = [];
|
|||
|
|
return Promise.resolve();
|
|||
|
|
}
|
|||
|
|
return new Promise((resolve) => {
|
|||
|
|
setTimeout(() => {
|
|||
|
|
action(phoneXYinfo.value[index], index);
|
|||
|
|
resolve();
|
|||
|
|
}, randomDelay(1, 5));//1-5秒随机延迟
|
|||
|
|
}).then(() => performActionsSequentially(actions, index));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 生成start秒到end秒的随机延迟
|
|||
|
|
function randomDelay(start, end) {
|
|||
|
|
return Math.floor(Math.random() * end * 1000) + start * 1000;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function start(udid, index) {
|
|||
|
|
isStopLike.value[index] = false;
|
|||
|
|
if (actions[index].length <= 0) {
|
|||
|
|
actions[index] = [
|
|||
|
|
(info, index) => clickxy(info.Likes.x, info.Likes.y, index),
|
|||
|
|
(info, index) => clickxy(info.Comment.x, info.Comment.y, index),
|
|||
|
|
(info, index) => clickxy(info.Comtext.x, info.Comtext.y, index, 1),
|
|||
|
|
(info, index) => clickxy(info.ComPush.x, info.ComPush.y, index, 2),
|
|||
|
|
(info, index) => clickxy(info.Attention.x, info.Attention.y, index, 3)
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
// 执行操作
|
|||
|
|
performActionsSequentially(actions[index], index);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function stop(udid, index) {
|
|||
|
|
actions[index] = [];
|
|||
|
|
isStopLike.value[index] = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//刷新方法
|
|||
|
|
function reloadfun() {
|
|||
|
|
reload()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.device-layout {
|
|||
|
|
display: flex;
|
|||
|
|
width: 100vw;
|
|||
|
|
height: 100vh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.device-list {
|
|||
|
|
width: 210px;
|
|||
|
|
min-width: 180px;
|
|||
|
|
background: #191c23;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
padding: 12px 0;
|
|||
|
|
border-right: 1px solid #333;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.device-mini {
|
|||
|
|
position: relative;
|
|||
|
|
cursor: pointer;
|
|||
|
|
border: 2px solid transparent;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
background: #23262f;
|
|||
|
|
margin: 0 8px;
|
|||
|
|
transition: border 0.2s;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.device-mini.active {
|
|||
|
|
border-color: #e83d3d;
|
|||
|
|
background: #242635;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mini-video,
|
|||
|
|
.mini-canvas {
|
|||
|
|
width: 160px;
|
|||
|
|
height: 90px;
|
|||
|
|
display: block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.device-main {
|
|||
|
|
flex: 1;
|
|||
|
|
position: relative;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
justify-content: center;
|
|||
|
|
background: #222;
|
|||
|
|
min-height: 100vh;
|
|||
|
|
overflow: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.main-video,
|
|||
|
|
.main-canvas {
|
|||
|
|
width: 352px;
|
|||
|
|
/* 160*2.2 */
|
|||
|
|
height: 792px;
|
|||
|
|
/* 360*2.2 */
|
|||
|
|
border-radius: 18px;
|
|||
|
|
box-shadow: 0 8px 40px #0008;
|
|||
|
|
position: absolute;
|
|||
|
|
top: 40px;
|
|||
|
|
left: 80px;
|
|||
|
|
z-index: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.main-controls {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 40px;
|
|||
|
|
right: 60px;
|
|||
|
|
min-width: 260px;
|
|||
|
|
max-width: 400px;
|
|||
|
|
background: rgba(40, 42, 58, 0.95);
|
|||
|
|
border-radius: 18px;
|
|||
|
|
box-shadow: 0 6px 30px #0005;
|
|||
|
|
padding: 18px 20px;
|
|||
|
|
z-index: 10;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 下面是你原本样式全可保留,按钮icon样式... */
|
|||
|
|
.open {
|
|||
|
|
background: url(../assets/open.png) no-repeat center center;
|
|||
|
|
background-size: 60% 60%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.Back {
|
|||
|
|
background: url(../assets/Back.png) no-repeat center center;
|
|||
|
|
background-size: 60% 60%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.Home {
|
|||
|
|
background: url(../assets/Home.png) no-repeat center center;
|
|||
|
|
background-size: 60% 60%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.Overview {
|
|||
|
|
background: url(../assets/Overview.png) no-repeat center center;
|
|||
|
|
background-size: 60% 60%;
|
|||
|
|
}
|
|||
|
|
</style>
|