From 1f2f59ef7c476deff49bcd2cf8c7959835b73b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=A1=E5=A4=8D=E4=B9=A0?= <2353956224@qq.com> Date: Tue, 15 Jul 2025 13:45:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 61 ++ package.json | 1 + src/App.vue | 9 +- src/api/account.js | 6 +- src/api/chat.js | 3 + src/components/ChatDialog.vue | 45 +- src/components/HostListDialog.vue | 107 +++ src/components/MultiLineInputDialog.vue | 107 +++ src/router/index.js | 2 +- src/static/css/app.less | 4 + src/static/css/video.less | 145 +++ src/utils/arrUtil.js | 21 + src/utils/axios.js | 136 +-- src/utils/fileUtil.js | 38 + src/utils/wsActions.js | 4 + src/views/HomeView.vue | 58 +- src/views/Untitled-1.vue | 1080 +++++++++++++++-------- src/views/VideoStream.vue | 398 ++------- vue.config.js | 3 + 19 files changed, 1384 insertions(+), 844 deletions(-) create mode 100644 src/components/HostListDialog.vue create mode 100644 src/components/MultiLineInputDialog.vue create mode 100644 src/static/css/app.less create mode 100644 src/static/css/video.less create mode 100644 src/utils/arrUtil.js create mode 100644 src/utils/fileUtil.js diff --git a/package-lock.json b/package-lock.json index 9fad416..11300cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "qwebchannel": "^6.2.0", "socket.io-client": "^4.8.1", "vue": "^3.2.13", + "vue-i18n": "^11.1.8", "vue-router": "^4.0.3", "vuex": "^4.0.0" }, @@ -2895,6 +2896,47 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@intlify/core-base": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.1.8.tgz", + "integrity": "sha512-BAdeGNapg9HL55k2QJPisa6y3FGnIqVK3Yjub2iUEuS88Jf4AY5hD8wm42FW6lEda921S8scWuKkmb6GUWKlqg==", + "dependencies": { + "@intlify/message-compiler": "11.1.8", + "@intlify/shared": "11.1.8" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.1.8.tgz", + "integrity": "sha512-4YCeg7L2kt89t6nKSSFACAnTBnBMXu0IfG49+pac2VWkWJ7h9AQcsOD3iCptMGuoEj7hcaoNA4F+K/qA7bJxZw==", + "dependencies": { + "@intlify/shared": "11.1.8", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.1.8.tgz", + "integrity": "sha512-Fpo7YgkT8jwOuSOwOQXrMwqdljEqdfSYdIFkGkpRi80xVCAXpc6MTzuP2pkuQVDXU9MPNC05TWrETzCr+zjuRA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", @@ -13507,6 +13549,25 @@ "dev": true, "license": "MIT" }, + "node_modules/vue-i18n": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.8.tgz", + "integrity": "sha512-2JHUseyUrjlguX2N72SAKZ4UBDZ2lo22gL2SMQ6jWJh98RB59nUIQNPE9xKKkSgK5cflj9un8SAwfjYg/PHMxw==", + "dependencies": { + "@intlify/core-base": "11.1.8", + "@intlify/shared": "11.1.8", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/vue-loader": { "version": "17.4.2", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.4.2.tgz", diff --git a/package.json b/package.json index c83492f..198d57d 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "qwebchannel": "^6.2.0", "socket.io-client": "^4.8.1", "vue": "^3.2.13", + "vue-i18n": "^11.1.8", "vue-router": "^4.0.3", "vuex": "^4.0.0" }, diff --git a/src/App.vue b/src/App.vue index af7bcb9..d73d452 100644 --- a/src/App.vue +++ b/src/App.vue @@ -3,12 +3,12 @@ - + \ No newline at end of file diff --git a/src/components/MultiLineInputDialog.vue b/src/components/MultiLineInputDialog.vue new file mode 100644 index 0000000..d175880 --- /dev/null +++ b/src/components/MultiLineInputDialog.vue @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index bf2ca9b..b12b5d3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -17,7 +17,7 @@ const routes = [ } ] const router = createRouter({ - history: createWebHistory(), + history: createWebHashHistory(), routes }) diff --git a/src/static/css/app.less b/src/static/css/app.less new file mode 100644 index 0000000..d606010 --- /dev/null +++ b/src/static/css/app.less @@ -0,0 +1,4 @@ +@bg-color: #022b4e; // 主色 +@bg-color-light: #022b4eaf; // 浅主色 +@bg-color-light-light: #022b4e1c; // 浅浅主色 +@btn-bg-color: #045dac; // 黄色按钮主色 \ No newline at end of file diff --git a/src/static/css/video.less b/src/static/css/video.less new file mode 100644 index 0000000..5c81bf4 --- /dev/null +++ b/src/static/css/video.less @@ -0,0 +1,145 @@ +body { + user-select: none; + +} + +.main { + display: flex; + width: 100vw; + height: 100vh; + background: #222; + +} + +.left { + background: #191c23; + width: 20vw; + box-sizing: content-box; +} + +.content { + width: 50vw; + display: grid; + grid-template-columns: repeat(3, minmax(160px, 320px)); + /* 每行 3 个,宽度自适应 */ + /* gap: 10px; */ +} + +.right { + width: 30vw; + background-color: #272727; +} + +.video-container { + position: relative; + // padding: 10px; + width: 100%; + + width: auto; + /* 取消 100%,避免换行 */ + display: inline-block; + display: flex; + transition: all 0.3s ease-in-out; + + .video-canvas { + position: absolute; + box-sizing: border-box; + } + + + .input-info { + color: rgb(255, 255, 255); + background-color: #424242; + position: absolute; + z-index: 10; + } +} + +video { + transition: all 0.3s ease-in-out; + + /* 关键:让 video 不拦截鼠标事件 */ + + /* 添加动画 */ +} + +.top-row { + align-items: flex-start; + /* 上对齐 */ +} + +.bottom-row { + align-items: flex-end; + /* 下对齐 */ + margin-top: auto; +} + +video { + /* position: relative; */ + width: 100%; + height: 100%; + position: absolute; + z-index: 1; + /* object-fit: contain; */ + /* transform: scale(0.27); */ + /* 缩小到原始尺寸的50% */ + /* transform-origin: top left; */ + /* 控制缩放原点 */ +} + +.canvas { + position: absolute; + top: 0; + left: 0; + z-index: 9; + /* transform: scale(0.27); */ + /* 缩小到原始尺寸的50% */ + /* transform-origin: top left; */ + /* 控制缩放原点 */ +} + +.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%; + +} + +.el-button { + width: 200px; + margin: 20px; + // background-color: darkcyan; + // color: white; + position: relative; + z-index: 999; +} + +.center-justify { + display: flex; + justify-content: space-around; + align-items: center; +} + +.center-line { + display: flex; + flex-direction: column; + align-items: center; + // justify-content: center; +} \ No newline at end of file diff --git a/src/utils/arrUtil.js b/src/utils/arrUtil.js new file mode 100644 index 0000000..5d7c75c --- /dev/null +++ b/src/utils/arrUtil.js @@ -0,0 +1,21 @@ +//分割数组 +export function splitArray(array, parts) { + if (!Array.isArray(array)) { + console.warn('splitArray: 第一个参数应为数组'); + return []; + } + const len = array.length; + const n = parseInt(parts, 10); + if (isNaN(n) || n <= 0) { + console.warn('splitArray: 份数应为大于 0 的整数'); + return []; + } + const result = []; + for (let i = 0; i < n; i++) { + // 计算第 i 份的起始和结束索引 + const start = Math.floor(i * len / n); + const end = Math.floor((i + 1) * len / n); + result.push(array.slice(start, end)); + } + return result; +} \ No newline at end of file diff --git a/src/utils/axios.js b/src/utils/axios.js index e8f7e63..8fc44df 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -4,31 +4,49 @@ */ import axios from 'axios' import { getToken, getUser } from '@/utils/storage' -import { useRouter } from 'vue-router'; -import { ElMessage } from 'element-plus'; +import router from '@/router' -const router = useRouter(); -// axios.defaults.withCredentials = true; +import { ElMessage } from 'element-plus'; +// import { usePythonBridge, } from '@/utils/pythonBridge' + +// const { stopScript } = usePythonBridge(); + +const specialBaseURL = 'http://120.26.251.180:15330' +const specialUrlPrefixes = ['chat', 'translation'] // 示例路径前缀 // 请求地址前缀 let baseURL = '' if (process.env.NODE_ENV === 'development') { // 生产环境 - // baseURL = "http://120.26.251.180:8085/" - baseURL = "http://120.26.251.180:15330" + // baseURL = "https://api.tkpage.yolozs.com" + // baseURL = "http://192.168.1.174:8101" + baseURL = "http://47.79.98.113:8101" } else { + // 测试环境 + // baseURL = "http://120.26.251.180:8085/" // 开发环境 - baseURL = "http://120.26.251.180:8085/" + + baseURL = "http://47.79.98.113:8101" + // baseURL = "http://api.tkpage.vvtiktok.cn" } // 请求拦截器 axios.interceptors.request.use((config) => { - // if (getToken()) { - // config.headers['token'] = getToken(); - // } + console.log("config", config) + const url = sliceUrl(config.url) + console.log("url", url) + if (!(config.url == 'doLogin' || config.url == 'get-id-by-name')) { + config.headers['vvtoken'] = getToken(); + } + // 判断是否是特殊接口 + const isSpecial = specialUrlPrefixes.some(prefix => config.url.includes(prefix)); + console.log("isSpecial", isSpecial) + // 根据接口设置 baseURL + config.baseURL = isSpecial ? specialBaseURL : baseURL; + console.log("config.baseURL", config.baseURL) // 请求超时时间 - 毫秒 config.timeout = 60000 - config.baseURL = baseURL + // config.baseURL = baseURL // 自定义Content-type config.headers['Content-type'] = 'application/json' return config; @@ -38,7 +56,20 @@ axios.interceptors.request.use((config) => { // 响应拦截器 axios.interceptors.response.use((response) => { - return response + console.log("response", response.data) + if (response.data.code == 0 || response.data.code == 200) { + console.log("response", response.data.data) + return response.data.data + } else if (response.data.code == 40400) { + // stopScript(); + router.push('/') + ElMessage.error(response.data.code + '' + response.data.message + 1); + } else { + + ElMessage.error(response.data.code + '' + response.data.message + 2); + Promise.reject(response.data.code + '' + response.data.message) + } + }, (error) => { // 可添加请求失败后的处理逻辑 return Promise.reject(error) @@ -54,24 +85,18 @@ export function getAxios({ url, params }) { params // 请求成功,将返回的数据传递给resolve函数 }).then(res => { - resolve(res.data) + resolve(res) // 请求失败,将错误信息传递给reject函数 }).catch(err => { - console.log(err) + ElMessage.error(err + 3); reject(err) + }) }) } // axios的post请求 export function postAxios({ url, data }) { - // if (url != 'api/account/login') { - - // throttledCheekalive(); - - // } - - return new Promise((resolve, reject) => { axios.post( url, @@ -82,20 +107,10 @@ export function postAxios({ url, data }) { } } ).then(res => { - resolve(res.data) + resolve(res) }).catch(err => { - if (err.message == "Network Error") { - // alert("网络错误,请检查网络连接") - // ElMessage.error('网络连接错误'); - reject('网络连接错误') - - } else { - ElMessage.error(err.message); - reject(err.message) - - } - // console.log(err) - // reject(err) + ElMessage.error(err + 4); + reject(err) }) }) } @@ -131,28 +146,29 @@ export const downFile = async (urlstr, data) => { } //请求前验证 -function cheekalive() { - axios.post('api/account/cheekalive', { - userId: getUser().userId, - currcode: getToken(), - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - } - } - ).then(res => { - console.log(res.data) - if (res.data) { +// function cheekalive() { +// axios.post('api/account/cheekalive', { +// userId: getUser().userId, +// currcode: getToken(), +// }, +// { +// headers: { +// 'Content-Type': 'application/x-www-form-urlencoded' +// } +// } +// ).then(res => { +// console.log(res.data) +// if (res.data) { - } else { - alert("账号在其他地方登录!") - window.location.href = '/'; - } +// } else { +// stopScript(); +// alert("账号在其他地方登录!") +// window.location.href = '/'; +// } - }) -} +// }) +// } //节流函数 function throttle(func, limit) { let inThrottle; @@ -167,6 +183,18 @@ function throttle(func, limit) { } } -const throttledCheekalive = throttle(cheekalive, 5000); +function sliceUrl(url) { + const lastSlash = url.lastIndexOf('/'); + const questionMark = url.indexOf('?'); + if (questionMark == -1) { + const result = url.slice(lastSlash + 1, url.length); + return result; + } else { + const result = url.slice(lastSlash + 1, questionMark); + return result; + } + +} + export default axios \ No newline at end of file diff --git a/src/utils/fileUtil.js b/src/utils/fileUtil.js new file mode 100644 index 0000000..bfaaded --- /dev/null +++ b/src/utils/fileUtil.js @@ -0,0 +1,38 @@ + +let filePath = '' + +export const chooseFile = async (udid, index, type, wsActions) => { + console.log('选择文件', window.electronAPI?.selectApkFile); + if (type == 1) { + if (window.electronAPI?.selectApkFile) { + const path = await window.electronAPI.selectApkFile() + if (path) { + filePath = path + console.log(filePath); + wsActions.install(udid, index, filePath) + } else { + filePath = '用户取消了选择' + console.log(filePath); + + } + } else { + filePath = '未检测到 Electron API,可能未正确注入 preload.js' + } + } else { + if (window.electronAPI?.selectFile) { + const path = await window.electronAPI.selectFile() + if (path) { + filePath = path + console.log(filePath); + wsActions.pushFile(udid, index, filePath) + } else { + filePath = '用户取消了选择' + console.log(filePath); + + } + } else { + filePath = '未检测到 Electron API,可能未正确注入 preload.js' + } + } + +} \ No newline at end of file diff --git a/src/utils/wsActions.js b/src/utils/wsActions.js index 907287e..359b18f 100644 --- a/src/utils/wsActions.js +++ b/src/utils/wsActions.js @@ -18,6 +18,9 @@ export function createWsActions(wslist, isStopLike = null) { // 所有业务操作方法 return { open: (udid, index) => send(index, { udid, action: 'openDY' }), //打开tk + killNow: (udid, index) => send(index, { udid, action: 'killNow' }), //关闭当前进程 + install: (udid, index, path) => send(index, { udid, action: 'install', resourceId: path }), //安装应用 + pushFile: (udid, index, path) => send(index, { udid, action: 'pushFile', resourceId: path }), //发送文件 slideDown: (udid, index) => send(index, { udid, action: 'slideDown' }),//下滑动视频 slideUp: (udid, index) => send(index, { udid, action: 'slideUp' }),//上滑动视频 slideRight: (udid, index) => send(index, { udid, action: 'slideRight' }),//右滑动视频 @@ -43,5 +46,6 @@ export function createWsActions(wslist, isStopLike = null) { toHost: (udid, index) => send(index, { udid, action: 'click', type: 'toHost', index, resourceId: 'com.zhiliaoapp.musically:id/iso' }), //进入主页二 hostVideo: (udid, index, num) => send(index, { udid, action: 'click', type: 'hostVideo', index, resourceId: 'com.zhiliaoapp.musically:id/d3u', num: num }), //主播视频 test: (udid, index) => send(index, { udid, action: 'click', type: 'test', index, resourceId: 'com.zhiliaoapp.musically:id/j7s' }), //截屏测试 + }; } diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index a40c1f9..6cc216c 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -38,7 +38,11 @@
- +
+ + +
import { ref, reactive, onMounted } from 'vue'; import { useRouter } from 'vue-router'; -import { login } from '@/api/account'; +import { login, getIdByName } from '@/api/account'; import { getToken, setToken, setUser, setUserPass, getUserPass } from '@/utils/storage'; -import { ElLoading } from 'element-plus'; +import { ElLoading, ElMessage } from 'element-plus'; let version = ref('0.0.0'); @@ -85,6 +89,7 @@ onMounted(() => { const router = useRouter(); const formData = ref({ + tenantName: getUserPass() == null ? '' : getUserPass().tenantName, userId: getUserPass() == null ? '' : getUserPass().userId, password: getUserPass() == null ? '' : getUserPass().password, }); @@ -92,41 +97,28 @@ const formData = ref({ const onSubmit = () => { - - - router.push('/Video'); - - return - const loading = ElLoading.service({ lock: true, text: 'Loading', background: 'rgba(0, 0, 0, 0.7)', }); setUserPass(formData.value); - login({ - userId: formData.value.userId, - password: formData.value.password, - source: 'app' - }).then((res) => { - loading.close(); - console.log(res) - if (res.code == 200) { - if (res.data.activeYn == 'Y') { - setToken(res.data.currcode); - setUser(res.data); - router.push('/nav'); - } else { - alert('账号未启用'); - } - - } else { - alert(res.mes); - } - - }).catch((err) => { - loading.close(); - }); + getIdByName(formData.value.tenantName).then((tenantId) => { + console.log("tenantId", tenantId) + login({ + tenantId: Number(tenantId), + username: formData.value.userId, + password: formData.value.password, + }).then((res) => { + loading.close(); + console.log(res) + setToken(res.tokenValue); + setUser(res); + router.push('/Video'); + }).catch((err) => { + loading.close(); + }); + }) }; @@ -207,7 +199,7 @@ const onSubmit = () => { .from { width: 420px; - height: 320px; + // height: 320px; color: #022b4e; background-color: #ffffff44; border-radius: 20px; diff --git a/src/views/Untitled-1.vue b/src/views/Untitled-1.vue index 0552d30..fb0eadc 100644 --- a/src/views/Untitled-1.vue +++ b/src/views/Untitled-1.vue @@ -1,101 +1,228 @@ - \ No newline at end of file diff --git a/src/views/VideoStream.vue b/src/views/VideoStream.vue index 00d2b15..05be9ff 100644 --- a/src/views/VideoStream.vue +++ b/src/views/VideoStream.vue @@ -6,11 +6,9 @@ --> - -
@@ -25,7 +23,7 @@ - 刷新 + 刷新
@@ -34,30 +32,25 @@ - 打开tiktok 一键养号 一键关注 + @click="showDialog = true; dialogTitle = '主播ID'; selectedDevice = 999">一键关注并打招呼 开启监测消息 关闭监测消息 全部停止 登出
-
-
-
-
-
- + :style="getVideoStyle(index)" @click.stop="selectedDevice = index"> @@ -106,49 +95,43 @@ 批量关注
- 导入评论 +
查看评论
- 导入私信 +
查看私信 检测消息 - 进入消息 - 获取聊天记录 - 获取屏幕尺寸 - + + 翻译本页对话 +
发送
截屏 + 关闭 + 安装 APK 文件 + 传送文件 -
- +
- 聊天 - - - + +
- + @confirm="onDialogConfirm" />
- - diff --git a/vue.config.js b/vue.config.js index ac25700..d7ee354 100644 --- a/vue.config.js +++ b/vue.config.js @@ -18,6 +18,9 @@ module.exports = defineConfig({ ] } + }, + less: { + additionalData: `@import "@/static/css/app.less";` // 注入全局变量文件 } } }