yolo助手AI ui 1.5.0

This commit is contained in:
2025-08-07 21:35:27 +08:00
parent a92c164af1
commit 85e399bf96
33 changed files with 888 additions and 990 deletions

View File

@@ -1,72 +1,18 @@
<template>
<div class="main">
<el-scrollbar class="left">
<div class=" center-line">
<!-- <el-button class="open" @click="wsActions.open(device.udid, index)"></el-button>
<el-button class="Back" @click="Back(device.udid, index)"></el-button>
<el-button class="Home" @click="Home(device.udid, index)"></el-button>
<el-button class="Overview" @click="Overview(device.udid, index)"></el-button> -->
<!-- <el-button @click="play(device.udid, index)">play</el-button> -->
<!-- <el-button class="open" @click="slideDown(device.udid, index)"></el-button>
<el-button class="open" @click="slideUp(device.udid, index)"></el-button>
<el-button class="open" @click="clickLike(device.udid, index)"></el-button> -->
<div></div>
<!-- <el-button @click="clickLikes(device.udid, index)">点赞</el-button> -->
<!-- <el-button @click="stopLike(index)">停止点赞</el-button> -->
<!-- <div></div>
<el-button @click="clickComment(device.udid, index)">评论</el-button>
<el-button @click="clickComtext(device.udid, index)">评论框</el-button>
<el-button @click="clickComPush(device.udid, index)">发布评论</el-button>
<div></div>
<el-button @click="clicktomy(device.udid, index)">主页</el-button> -->
<!-- <el-button @click="wsActions.clickAttention(device.udid, index)">关注/私信</el-button> -->
<!-- <div></div>
<el-button @click="clickPrivatetext(device.udid, index)">私信输入</el-button>
<el-button @click="clickPrivatePush(device.udid, index)">私信发送</el-button> -->
<el-button type="warning" @click="reload()">刷新</el-button>
<!-- <el-button type="warning" @click="opentanchuan()">123</el-button> -->
<div></div>
<!-- <el-button @click="wsActions.clickCopy(device.udid, index)">找私信</el-button> -->
<!-- <el-button @click="wsActions.clickCopyList(device.udid, index)">私信列表</el-button> -->
<div></div>
<!-- <el-button @click="wsActions.getmesNum(device.udid, index)">获取收件箱</el-button> -->
<!-- <el-button @click="wsActions.getSize(device.udid, index)">获取屏幕尺寸</el-button> -->
<!-- <el-button @click="wsActions.slideRight(device.udid, index)">右滑</el-button> -->
<!-- <el-button @click="wsActions.isHost(device.udid, index)">一键养号</el-button> -->
<el-button type="success" @click="openTk()">打开tiktok</el-button>
<el-button type="success" @click="resetTk()">重置tiktok</el-button>
<el-button type="success" @click="brushLive()">打开直播</el-button>
<el-button :type="runType[0] == 'like' ? 'danger' : 'success'" @click="parentNum()">{{ runType[0] == 'like' ?
'养号中' : '一键养号' }}</el-button>
<el-button type="success"
@click="showDialog = true; dialogTitle = '主播ID'; selectedDevice = 999">一键关注并打招呼</el-button>
<el-button type="success" v-if="!isShowMes" @click="openMonitor()">开启监测消息</el-button>
<el-button type="danger" v-else @click="cloesMonitor()">关闭监测消息</el-button>
<el-button type="danger" @click="stop()">全部停止</el-button>
<el-button type="danger" @click="router.push('/')">登出</el-button>
<div></div>
<!-- <div style="display: flex;">
<div style="width: 150px;">主播id</div>
<el-input style="border: 1px solid #000;" v-model="hostIdContent[index]" type="text"></el-input>
<el-button @click="setHostId(index)">发送</el-button>
</div>
<div style="display: flex;">
<div style="width: 150px;">评论内容</div>
<el-input style="border: 1px solid #000;" v-model="textContent[index]" type="text"></el-input>
<el-button @click="setComText(index)">发送</el-button>
</div> -->
<!-- <div style="display: flex;">
<div style="width: 150px;">私信内容</div>
<el-input style="border: 1px solid #000;" v-model="textContentpri[index]" type="text"></el-input>
<el-button @click="setPrivateText(index)">发送</el-button>
</div> -->
<div></div>
<!-- <el-button @click="getText(index)">获取粘贴板内容</el-button> -->
<div></div>
<!-- <el-button @click="wsActions.isVideoAndLive(device.udid, index)">判断视频还是直播</el-button> -->
<el-scrollbar class="left"> <!-- 左边栏 -->
<div class="center-line"> <!-- 左边栏按钮 -->
<div v-for="(btn, index) in buttons" :key="index" style="width: 100%;">
<div v-if="btn.show?.()" class="left-button" :style="{
backgroundColor: btn.label == '关闭监测消息' ? 'red' : '',
}" @click="btn.onClick" @mouseenter="hoverIndex = index" @mouseleave="hoverIndex = null">
<img :src="hoverIndex === index ? btn.img.hover : btn.img.normal" alt="">
{{ btn.label }}
</div>
</div>
</div>
</el-scrollbar>
<!-- 中间手机区域 -->
<div class="content" @click.self="selectedDevice = 999">
<div class="video-container" @click.self="selectedDevice = 999" v-for="(device, index) in deviceInformation"
:key="device.udid" @mouseup="(e) => handleCanvasup(device.udid, e, index)">
@@ -75,50 +21,42 @@
:style="getVideoStyle(index)" @click.stop="selectedDevice = index"></video>
<canvas class="canvas" v-show="selectedDevice == index" :ref="(el) => (canvasRef[device.udid] = el)"
@mousemove.stop="(e) => handleMouseMove(device.udid, e, index)"
@mousedown.stop="(e) => handleCanvasdown(device.udid, e, index)">
@mousedown.stop="(e) => handleCanvasdown(device.udid, e, index)" :style="{
transform: getTransformStyle(index)
}">
</canvas>
</div>
<div class="input-info" v-show="selectedDevice == index" :style="{ left: phone.width * 1.4 + 4 + '0px' }">
<!-- <div class="input-info" v-show="false"> -->
<!-- <el-button @click="showDialog = true; dialogTitle = '主播ID';">批量关注</el-button> -->
<div></div>
<!-- <el-button @click="showDialog = true; dialogTitle = '评论';">导入评论</el-button> -->
<div></div>
<el-button @click="getComArr(index, '评论')">查看评论</el-button>
<div></div>
<!-- <el-button @click="showDialog = true; dialogTitle = '私信';">导入私信</el-button> -->
<div></div>
<el-button @click="getComArr(index, '私信')">查看私信</el-button>
<!-- <el-button @click="wsActions.search(device.udid, index)">搜索</el-button> -->
<!-- <el-button @click="wsActions.getmesNum(device.udid, index)">检测消息</el-button> -->
<!-- <el-button @click="wsActions.clickMesage(device.udid, index)">进入消息</el-button> -->
<el-button @click="wsActions.clickSysMesage(device.udid, index)">进入消息</el-button>
<el-button @click="resetApp(device.udid, index)">重置应用</el-button>
<el-button
@click="wsActions.clickCopyList(device.udid, index); openShowChat = true; istranslate = true">翻译本页对话</el-button>
<!-- <el-button @click="wsActions.getSize(device.udid, index)">获取屏幕尺寸</el-button> -->
<div class="input-info" v-show="selectedDevice == index"
:style="{ left: phone.width * 1.4 + 4 + '0px', transform: getTransformStyle(index), }">
<div class="app-button" @click="resetApp(device.udid, index)">重置应用</div>
<div class="app-button"
@click="wsActions.clickCopyList(device.udid, index); openShowChat = true; istranslate = true">
翻译本页对话</div>
<div class="app-button" @click="wsActions.clickCopyList(device.udid, index); openShowChat = true;">
回复消息</div>
<!-- <div class="app-button" @click="wsActions.getSize(device.udid, index)">获取屏幕尺寸</div> -->
<div class="app-button" @click="wsActions.test(device.udid, index)">打印ui节点树</div>
<div class="app-button" @click="wsActions.isOneLive(device.udid, index)">判断单人还是双人</div>
<div class="app-button" @click="wsActions.slideDown(device.udid, index)">下滑</div>
<div class="app-button" @click="wsActions.killNow(device.udid, index)">关闭当前应用</div>
<div class="app-button" @click="chooseFile(device.udid, index, 1, wsActions)">安装 APK
文件</div>
<div class="app-button" @click="chooseFile(device.udid, index, 2, wsActions)">
传送文件</div>
<div style="display: flex;">
<el-input style="border: 1px solid #000;" v-model="textContent[index]" type="text"></el-input>
<el-button @click="setComText(index)">发送</el-button>
<input style="border: 1px solid #000;margin:0px 14px;" v-model="textContent[index]" type="text"></input>
<div class="app-button" style="margin: 0px;height: 40px;width: 60px;font-size: 14px;"
@click="setComText(index)">发送
</div>
</div>
<el-button @click="wsActions.test(device.udid, index)">打印ui节点树</el-button>
<el-button @click="wsActions.isOneLive(device.udid, index)">判断单人还是双人</el-button>
<el-button @click="wsActions.slideDown(device.udid, index)">下滑</el-button>
<el-button @click="wsActions.killNow(device.udid, index)">关闭当前应用</el-button>
<el-button @click="chooseFile(device.udid, index, 1, wsActions)">安装 APK 文件</el-button>
<el-button @click="chooseFile(device.udid, index, 2, wsActions)">传送文件</el-button>
<!-- <el-button @click="wsActions.isHost(device.udid, index)">一键养号</el-button> -->
<!-- <div class="app-button" @click="wsActions.isHost(device.udid, index)">一键养号</div> -->
</div>
</div>
<!--
<div class="video-container" @click.self="selectedDevice = 999" v-for="item in 4" :style="getVideoStyle()"
:class="{ 'bottom-row': item >= 2 }">
<div style="position: relative;box-sizing: border-box; ">
</div>
</div> -->
</div>
<div class="right">
<!-- <el-button @click="openShowChat = !openShowChat">聊天</el-button> -->
<div class="right" @click.self="selectedDevice = 999">
<div style="margin: 14px;"></div>
<ChatDialog :visible="openShowChat" :messages="chatList" />
</div>
<MultiLineInputDialog v-model:visible="showDialog" :initialText='""' :title="dialogTitle" :index="selectedDevice"
@@ -130,7 +68,12 @@
import { ref, onMounted, onUnmounted, onBeforeUnmount, watch, inject } from "vue";
import VideoConverter from "h264-converter";
import { useRouter } from 'vue-router';
import { setphoneXYinfo, getphoneXYinfo, getUser, getHostList, setHostList, getContentpriList, setContentpriList, getContentList, setContentList } from '@/utils/storage'
import {
setphoneXYinfo, getphoneXYinfo, getUser,
getHostList, setHostList, getContentpriList,
setContentpriList, getContentList, setContentList,
setsessionId, getsessionId
} from '@/stores/storage'
import { toBufferBtn, stringToUtf8ByteArray, getClipboard, setClipboard, bufferToString, startsWithHeader, trimLongArray, base64ToBinary, toBuffer } from '@/utils/bufferUtils';
import { createWsActions } from '@/utils/wsActions';
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
@@ -162,7 +105,7 @@ let dialogTitle = ref('');
//评论文本内容
let textContent = ref(['', '', '', '', '', '', '', '']);
let textContentArr = ref([[], [], [], [], [], [], [], [], []]);
//主播id内容
//当前主播id内容
let hostIdArr = ref([{}, {}, {}, {}, {}, {}, {}, {}]);
// let hostIdContentArr = ref([[], [], [], [], [], [], [], [], []]);
//私信文本内容
@@ -185,6 +128,7 @@ let instanceList = ref([{}, {}, {}, {}, {}, {}, {}, {}]);
//是否是在关注主播
let runType = ref(['', '', '', '', '', '', '', '']);
//屏幕尺寸系数
let isMonitor = ref(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)
@@ -207,11 +151,113 @@ const mouseData = {
buttons: 1,
};
//打开聊天窗口的状态
let openShowChat = ref(false);
let openShowChat = ref(true);
let istranslate = ref(false); //是否是翻译本页
let phoneXYinfo = ref(getphoneXYinfo() == null ? [{}, {}, {}, {}, {}, {}, {}, {}] : getphoneXYinfo());
console.log('phoneXYinfo.value', phoneXYinfo.value)
// 当前悬浮的按钮索引
const hoverIndex = ref(null)
// 你可以用这种方式声明按钮们
const buttons = [
{
label: '刷新',
onClick: () => reload(),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn1.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn1-1.png', import.meta.url).href
}
},
{
label: '打开tiktok',
onClick: () => openTk(),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn2.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn2-2.png', import.meta.url).href
}
},
{
label: '重置tiktok',
onClick: () => resetTk(),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn3.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn3-3.png', import.meta.url).href
}
},
{
label: '打开直播',
onClick: () => brushLive(),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn4.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn4-4.png', import.meta.url).href
}
},
{
label: '一键养号',
onClick: () => parentNum(),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn5.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn5-5.png', import.meta.url).href
}
},
{
label: '一键关注并打招呼',
onClick: () => {
showDialog.value = true
dialogTitle.value = '主播ID'
selectedDevice.value = 999
},
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn6.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn6-6.png', import.meta.url).href
}
},
{
label: '开启监测消息',
onClick: () => openMonitor(),
show: () => !isShowMes.value, // 只有在未开启时显示
img: {
normal: new URL('@/assets/video/leftBtn1.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn1-1.png', import.meta.url).href
}
},
{
label: '关闭监测消息',
onClick: () => cloesMonitor(),
show: () => isShowMes.value, // 只有在已开启时显示
img: {
normal: new URL('@/assets/video/leftBtn1.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn1-1.png', import.meta.url).href
},
style: { backgroundColor: 'red' }
},
{
label: '全部停止',
onClick: () => stop(),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn8.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn8-8.png', import.meta.url).href
}
},
{
label: '登出',
onClick: () => router.push('/'),
show: () => true,
img: {
normal: new URL('@/assets/video/leftBtn9.png', import.meta.url).href,
hover: new URL('@/assets/video/leftBtn9-9.png', import.meta.url).href
}
}
]
const wsCache = new Map();
//``````````````````````````````````````````````````````````````````````````````````
// 初始化 手机显示WebSocket 和视频流
const initVideoStream = (udid, index) => {
@@ -296,9 +342,11 @@ const initVideoStream = (udid, index) => {
//点击进入新消息页面以后,获取页面信息
wsActions.clickCopyList(deviceInformation.value[index].udid, index)
} else if (resData.type == 'clickSysMesage') {
Back('', index)
setTimeout(() => {
Back('', index)
}, 3000)
}, 1000)
} else if (resData.type == 'isVideoAndLive') {
console.log(resData.message)
} else if (resData.type == 'clickCopyList') { //获取到的消息列表
@@ -314,11 +362,13 @@ const initVideoStream = (udid, index) => {
if (mesBox.position == 'right') return
openShowChat.value = true
console.log("执行ai")
chat({ msg: mesBox.text }).then(res => {
console.log("ai返回", res)
textContentpri.value[index] = res.result
PrivatetexToPrivatePush(deviceInformation.value[index].udid, index)
})
} else {
console.log("翻译本页")
istranslate.value = false
@@ -396,9 +446,13 @@ const initVideoStream = (udid, index) => {
Back('', index);
setTimeout(() => {
Back('', index);
//正常没有消息,发送完私信以后,返回六次,然后继续下一个任务
wsActions.getmesNum(deviceInformation.value[index].udid, index)
// LikesToLikesToLikes(deviceInformation.value[index].udid, index)
if (isMonitor.value) {
//正常没有消息,发送完私信以后,返回六次,然后继续下一个任务
wsActions.getmesNum(deviceInformation.value[index].udid, index)
} else {
LikesToLikesToLikes(deviceInformation.value[index].udid, index)
}
}, 1000);
}, 1000);
@@ -506,7 +560,7 @@ const initVideoStream = (udid, index) => {
}
} else {
// ----------------------------------------------------------------------------------------------------报错处理
//如果该视频无法被评论,返回刷下一条视频
//如果该视频无法被评论,或者没有评论,返回刷下一条视频
if (resData.type == 'Comtext' || resData.type == 'CommentText') {
if (runType.value[index] == 'follow') {
@@ -533,7 +587,7 @@ const initVideoStream = (udid, index) => {
LikesToLikesToLikes(deviceInformation.value[index].udid, index)
}, 1000)
}, 1000)
} else if (resData.type == 'Privatetex' || resData.type == 'hostVideo' || resData.type == 'search') {
} else if (resData.type == 'Privatetex' || resData.type == 'hostVideo' || resData.type == 'search' || resData.type == 'Attention' || resData.type == 'Comment') {
if (runType.value[index] == 'follow') {
//关注的时候出现无法私信和没有视频的情况 错误重置
resetApp(udid, index)
@@ -756,6 +810,7 @@ onMounted(() => {
if (data === 'start') {
if (!isMsgPop.value) {
isMsgPop.value = true;
ElMessageBox.confirm(
'检测到YOLO助手正在爬取主播是否进行操作',
'消息提醒',
@@ -767,7 +822,6 @@ onMounted(() => {
)
.then(() => {
//开启sse版follow任务
ElMessage({
type: 'success',
message: '任务开启成功',
@@ -807,75 +861,26 @@ onMounted(() => {
})
}
} else {
stroageHost.value = getHostList()
// stroageHost.value = getHostList()
stroageHost.value.push(({ country: data.country, text: data.hostsId, state: false }))
if (isMsgPop.value) {
if (runType.value[0] == 'follow') {
setHostList(stroageHost.value)
}
}
//更新状态
// update(
// {
// id: data.id,
// operationStatus: 1,
// }
// ).then(() => {
// })
})
});
//更新状态
// update(
// {
// id: data.id,
// operationStatus: 1,
// }
// ).then(() => {
function opentanchuan() {
ElMessageBox.confirm(
'接收到YOLO爬虫爬取到的主播开始进行操作',
'消息提醒',
{
confirmButtonText: '开始',
cancelButtonText: '取消',
type: 'success',
}
)
.then(() => {
ElMessage({
type: 'success',
message: '任务开启成功',
})
resetTk()
comment().then((resA) => {
console.log('resA:', resA);
setContentList(resA)
//评论
textContentArr.value.forEach((item, indexA) => {
textContent.value[indexA] = resA[getRandomNumber(resA.length - 1)];
})
prologue().then((resB) => {
console.log('resB:', resB);
setContentpriList(resB)
//私信
textContentpriArr.value.forEach((item, indexA) => {
textContentpri.value[indexA] = resB[getRandomNumber(resB.length - 1)];
runType.value[indexA] = 'follow'
console.log('runType', runType.value[indexA])
})
deviceInformation.value.forEach((device, indexB) => {
if (getHostList().length <= 0) return;
// LikesToLikesToLikes(device.udid, indexB)
wsActions.getmesNum(device.udid, indexB)
})
})
})
})
.catch(() => {
})
}
// })
onBeforeUnmount(() => {
document.removeEventListener("visibilitychange", handleVisibilityChange);
@@ -1313,7 +1318,7 @@ function getVideoStyle(index) {
const isSelected = selectedDevice.value === index;
const baseWidth = phone.value.width;
const baseHeight = phone.value.height;
// console.log(isSelected, '是否相等')
return {
width: isSelected ? baseWidth * 1.4 + 'px' : baseWidth + 'px',
height: isSelected ? baseHeight * 1.4 + 'px' : baseHeight + 'px',
@@ -1323,6 +1328,8 @@ function getVideoStyle(index) {
left: isSelected ? '0' : 'unset',
zIndex: isSelected ? 1000 : 1,
pointerEvents: isSelected ? 'none' : 'auto',
transform: getTransformStyle(index),
transition: 'all 0.3s ease',
};
}
@@ -1400,20 +1407,9 @@ function brushLive() {
})
}
//确认多行文本框内容
function onDialogConfirm(result, type, index) {
console.log(result, type, index);
function onDialogConfirm(result, type, index, isMon) {
console.log(type, index, isMon);
if (type == '评论') {
//index ==999 表示批量养号,输入完评论后 即可直接执行脚本
// if (index == 999) {
// getContentList().forEach((item, indexA) => {
// // textContentArr.value[indexA] = result;
// textContent.value[indexA] = result[getRandomNumber(result.length - 1)];
// })
// setContentList(result)
// console.log(getContentList())
// parentNum()
// //index==998是批量关注主播 输入完评论后 还需要输入私信内容
// } else
if (index == 998) {
textContentArr.value.forEach((item, indexA) => {
textContent.value[indexA] = result[getRandomNumber(result.length - 1)];
@@ -1433,17 +1429,26 @@ function onDialogConfirm(result, type, index) {
} else if (type == '私信') {
//index ==999 表示全部
if (index == 999) {
isMonitor.value = isMon //是否自动回复
textContentpriArr.value.forEach((item, indexA) => {
textContentpri.value[indexA] = result[getRandomNumber(result.length - 1)];
runType.value[indexA] = 'follow'
})
// isStop.value = true; //停止所有任务
setContentpriList(result)
deviceInformation.value.forEach((device, indexB) => {
if (getHostList().length <= 0) return;
if (isMon) {
console.log(isMon)
console.error('自动回复');
wsActions.getmesNum(device.udid, indexB)
} else {
console.error('开始关注');
LikesToLikesToLikes(device.udid, indexB)
}
// LikesToLikesToLikes(device.udid, indexB)
wsActions.getmesNum(device.udid, indexB)
})
} else {
textContentpriArr.value[index] = result;
@@ -1465,15 +1470,6 @@ function onDialogConfirm(result, type, index) {
showDialog.value = true;
}, 600)
}
// else {
// hostIdContentArr.value[index] = result;
// hostIdContent.value[index] = result[0];
// deviceInformation.value.forEach((device, indexA) => {
// if (index == indexA) {
// LikesToLikesToLikes(device.udid, index)
// }
// })
// }
}
}
@@ -1495,8 +1491,16 @@ function markFirstFalseAsTrue(hostList) {
}
return null; // 没有找到 false 的项
}
//计算手机canvas是否需要偏移
function getTransformStyle(index) {
return selectedDevice.value === index && index >= 3
? 'translateY(-30%)'
: 'none';
}
function manualGc() {
window.electronAPI.manualGc()
}
</script>
<style scoped lang="less">