分包
This commit is contained in:
61
package-lock.json
generated
61
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<router-view v-if="isRouterAlive" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
provide() {
|
||||
return {
|
||||
return {
|
||||
reload: this.reload
|
||||
}
|
||||
},
|
||||
@@ -21,7 +21,7 @@ export default {
|
||||
reload() {
|
||||
// 先将组件隐藏
|
||||
this.isRouterAlive = false
|
||||
|
||||
|
||||
// 使用nextTick确保DOM更新后再重新显示组件
|
||||
this.$nextTick(() => {
|
||||
this.isRouterAlive = true
|
||||
@@ -58,8 +58,9 @@ window.ResizeObserver = class ResizeObserver extends _ResizeObserver {
|
||||
grid-template-rows: auto 1fr;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* #vite-error-overlay { display: none !important; } 隐藏vite错误提示 */
|
||||
.control-area {
|
||||
.control-area {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
@@ -4,7 +4,11 @@ export function apiGetCart() {
|
||||
return getAxios({ url: '/cgi-bin/cart/latest' })
|
||||
}
|
||||
export function login(data) {
|
||||
return postAxios({ url: 'api/account/login', data })
|
||||
return postAxios({ url: '/api/user/aiChat-doLogin', data })
|
||||
}
|
||||
|
||||
export function getIdByName(name) {
|
||||
return getAxios({ url: `/api/tenant/get-id-by-name?name=${name}` })
|
||||
}
|
||||
export function cheekalive(data) {
|
||||
return postAxios({ url: 'api/account/cheekalive', data })
|
||||
|
||||
@@ -5,3 +5,6 @@ export function chat(data) {
|
||||
return postAxios({ url: '/chat', data })
|
||||
}
|
||||
|
||||
export function translation(data) {
|
||||
return postAxios({ url: '/translation', data })
|
||||
}
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
<div v-if="visible" class="dialog-overlay" @click.self="close">
|
||||
<div class="dialog-content">
|
||||
<h3 class="text-lg font-bold mb-4">最近一条的消息翻译</h3>
|
||||
<div class="chat-box">
|
||||
<div class="left-message">
|
||||
<div class="bubble left">{{ leftMsg }}</div>
|
||||
<el-scrollbar class="chat-box">
|
||||
<div v-for="(msg, index) in messages" :key="index"
|
||||
:class="msg.position === 'left' ? 'left-message' : 'right-message'">
|
||||
<div :class="['bubble', msg.position]">{{ msg.text }}</div>
|
||||
</div>
|
||||
<div class="right-message">
|
||||
<div class="bubble right">{{ rightMsg }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <button class="close-btn" @click="close">关闭</button> -->
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -19,24 +16,21 @@
|
||||
import { defineProps, defineEmits } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
leftMsg: String,
|
||||
rightMsg: String,
|
||||
visible: Boolean
|
||||
visible: Boolean,
|
||||
messages: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
// const emit = defineEmits(['close'])
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
// const close = () => emit('close')
|
||||
const close = () => emit('close')
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-overlay {
|
||||
/* position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0; */
|
||||
/* background: rgba(0, 0, 0, 0.5); */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -53,29 +47,27 @@ const props = defineProps({
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
.left-message {
|
||||
align-self: flex-start;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.right-message {
|
||||
align-self: flex-end;
|
||||
text-align: right;
|
||||
margin-bottom: 20px;
|
||||
|
||||
}
|
||||
|
||||
.bubble {
|
||||
padding: 10px 14px;
|
||||
border-radius: 18px;
|
||||
max-width: 70%;
|
||||
|
||||
display: inline-block;
|
||||
/* 👈 使气泡宽度自适应内容 */
|
||||
padding: 10px 14px;
|
||||
border-radius: 18px;
|
||||
max-width: 70%;
|
||||
word-break: break-word;
|
||||
/* 防止英文单词太长撑爆 */
|
||||
}
|
||||
|
||||
.bubble.left {
|
||||
@@ -85,7 +77,8 @@ const props = defineProps({
|
||||
.bubble.right {
|
||||
background-color: rgb(0, 169, 214);
|
||||
color: white;
|
||||
|
||||
text-align: left;
|
||||
/* ✅ 关键:强制文字左对齐 */
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
|
||||
107
src/components/HostListDialog.vue
Normal file
107
src/components/HostListDialog.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<el-dialog draggable :title="title" v-model="visibleLocal" width="600px" @close="handleCancel">
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
|
||||
// 定义接收的 props
|
||||
const props = defineProps({
|
||||
/** 对话框可见性,外部通过 v-model:visible 绑定 */
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/** 对话框标题 */
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/** 文本框初始内容,可选 */
|
||||
initialText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/** 文本框行数 */
|
||||
type: {
|
||||
type: Number,
|
||||
default: 10,
|
||||
},
|
||||
/** index */
|
||||
index: {
|
||||
type: Number,
|
||||
default: 999,
|
||||
},
|
||||
/** 文本框占位符 */
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '每行一条,支持粘贴多行后自动拆分',
|
||||
},
|
||||
/** 是否去重,默认 true */
|
||||
dedupe: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 定义 emits
|
||||
const emit = defineEmits(['update:visible', 'confirm', 'cancel']);
|
||||
|
||||
// 本地 rawText,用于绑定 textarea
|
||||
const rawText = ref(props.initialText);
|
||||
|
||||
// 当 props.initialText 变化时,更新 rawText
|
||||
watch(
|
||||
() => props.initialText,
|
||||
(newVal) => {
|
||||
rawText.value = newVal;
|
||||
}
|
||||
);
|
||||
|
||||
// 计算属性,用于 v-model:visible 绑定 el-dialog
|
||||
const visibleLocal = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:visible', val);
|
||||
},
|
||||
});
|
||||
|
||||
/** 解析 rawText 为数组:按行拆分,trim,去空,去重(如 dedupe=true) */
|
||||
function parseLines() {
|
||||
const lines = rawText.value
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0);
|
||||
if (props.dedupe) {
|
||||
return Array.from(new Set(lines));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/** 点击确定按钮 */
|
||||
function handleConfirm() {
|
||||
const items = parseLines();
|
||||
emit('confirm', items, props.title, props.index);
|
||||
// 关闭对话框
|
||||
emit('update:visible', false);
|
||||
rawText.value = '';
|
||||
}
|
||||
|
||||
/** 点击取消或对话框关闭 */
|
||||
function handleCancel() {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 可根据项目风格调整 */
|
||||
</style>
|
||||
107
src/components/MultiLineInputDialog.vue
Normal file
107
src/components/MultiLineInputDialog.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<el-dialog draggable :title="title" v-model="visibleLocal" width="600px" @close="handleCancel">
|
||||
<el-input type="textarea" v-model="rawText" :rows="10" :placeholder="placeholder" clearable></el-input>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
|
||||
// 定义接收的 props
|
||||
const props = defineProps({
|
||||
/** 对话框可见性,外部通过 v-model:visible 绑定 */
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
/** 对话框标题 */
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/** 文本框初始内容,可选 */
|
||||
initialText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/** 文本框行数 */
|
||||
type: {
|
||||
type: Number,
|
||||
default: 10,
|
||||
},
|
||||
/** index */
|
||||
index: {
|
||||
type: Number,
|
||||
default: 999,
|
||||
},
|
||||
/** 文本框占位符 */
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '每行一条,支持粘贴多行后自动拆分',
|
||||
},
|
||||
/** 是否去重,默认 true */
|
||||
dedupe: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
// 定义 emits
|
||||
const emit = defineEmits(['update:visible', 'confirm', 'cancel']);
|
||||
|
||||
// 本地 rawText,用于绑定 textarea
|
||||
const rawText = ref(props.initialText);
|
||||
|
||||
// 当 props.initialText 变化时,更新 rawText
|
||||
watch(
|
||||
() => props.initialText,
|
||||
(newVal) => {
|
||||
rawText.value = newVal;
|
||||
}
|
||||
);
|
||||
|
||||
// 计算属性,用于 v-model:visible 绑定 el-dialog
|
||||
const visibleLocal = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set(val) {
|
||||
emit('update:visible', val);
|
||||
},
|
||||
});
|
||||
|
||||
/** 解析 rawText 为数组:按行拆分,trim,去空,去重(如 dedupe=true) */
|
||||
function parseLines() {
|
||||
const lines = rawText.value
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => line.length > 0);
|
||||
if (props.dedupe) {
|
||||
return Array.from(new Set(lines));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/** 点击确定按钮 */
|
||||
function handleConfirm() {
|
||||
const items = parseLines();
|
||||
emit('confirm', items, props.title, props.index);
|
||||
// 关闭对话框
|
||||
emit('update:visible', false);
|
||||
rawText.value = '';
|
||||
}
|
||||
|
||||
/** 点击取消或对话框关闭 */
|
||||
function handleCancel() {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 可根据项目风格调整 */
|
||||
</style>
|
||||
@@ -17,7 +17,7 @@ const routes = [
|
||||
}
|
||||
]
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
|
||||
4
src/static/css/app.less
Normal file
4
src/static/css/app.less
Normal file
@@ -0,0 +1,4 @@
|
||||
@bg-color: #022b4e; // 主色
|
||||
@bg-color-light: #022b4eaf; // 浅主色
|
||||
@bg-color-light-light: #022b4e1c; // 浅浅主色
|
||||
@btn-bg-color: #045dac; // 黄色按钮主色
|
||||
145
src/static/css/video.less
Normal file
145
src/static/css/video.less
Normal file
@@ -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;
|
||||
}
|
||||
21
src/utils/arrUtil.js
Normal file
21
src/utils/arrUtil.js
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
38
src/utils/fileUtil.js
Normal file
38
src/utils/fileUtil.js
Normal file
@@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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' }), //截屏测试
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,7 +38,11 @@
|
||||
|
||||
<div class="from-input">
|
||||
<el-form label-position="left" label-width="100px" :model="formData">
|
||||
|
||||
<div class="from-input-item1">
|
||||
<img src="@/assets/username.png" alt="">
|
||||
<el-input style="height: 25px;" v-model="formData.tenantName" placeholder="租户号"
|
||||
clearable @keyup.enter="onSubmit" />
|
||||
</div>
|
||||
<div class="from-input-item1">
|
||||
<img src="@/assets/username.png" alt="">
|
||||
<el-input style="height: 25px;" v-model="formData.userId" placeholder="账号" clearable
|
||||
@@ -70,9 +74,9 @@
|
||||
<script setup>
|
||||
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();
|
||||
});
|
||||
})
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -207,7 +199,7 @@ const onSubmit = () => {
|
||||
|
||||
.from {
|
||||
width: 420px;
|
||||
height: 320px;
|
||||
// height: 320px;
|
||||
color: #022b4e;
|
||||
background-color: #ffffff44;
|
||||
border-radius: 20px;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,9 @@
|
||||
<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="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> -->
|
||||
@@ -25,7 +23,7 @@
|
||||
<!-- <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="reloadfun()">刷新</el-button>
|
||||
<el-button type="warning" @click="reload()">刷新</el-button>
|
||||
<div></div>
|
||||
<!-- <el-button @click="wsActions.clickCopy(device.udid, index)">找私信</el-button> -->
|
||||
<!-- <el-button @click="wsActions.clickCopyList(device.udid, index)">私信列表</el-button> -->
|
||||
@@ -34,30 +32,25 @@
|
||||
<!-- <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="showDialog = true; dialogTitle = '评论'; selectedDevice = 999">一键养号</el-button>
|
||||
<el-button type="success"
|
||||
@click="showDialog = true; dialogTitle = '主播ID'; selectedDevice = 999">一键关注</el-button>
|
||||
@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></div>
|
||||
<!-- <el-button @click="wsActions.test(device.udid, index)">截屏</el-button> -->
|
||||
<div></div>
|
||||
<!-- <el-button @click="wsActions.search(device.udid, index)">搜索</el-button>
|
||||
<div></div>
|
||||
|
||||
<el-button @click="wsActions.searchHost(device.udid, index)">搜主播</el-button>
|
||||
<div></div>
|
||||
|
||||
<el-button @click="wsActions.toHost(device.udid, index)">主页</el-button>
|
||||
<div></div>
|
||||
<el-button @click="LikesToLikesToLikes(device.udid, index)">批量关注</el-button> -->
|
||||
|
||||
<div></div>
|
||||
<!-- <div style="display: flex;">
|
||||
<div style="width: 150px;">主播id</div>
|
||||
@@ -80,23 +73,19 @@
|
||||
<!-- <el-button @click="clickxy(284, 392, index, 9)">长按</el-button> -->
|
||||
<!-- <el-button @click="getText(index)">获取粘贴板内容</el-button> -->
|
||||
<div></div>
|
||||
|
||||
<!-- <el-button @click="LikesToCommentToComPush(device.udid, index)">设置自动化坐标</el-button> -->
|
||||
<!-- <el-button @click="start(device.udid, index)">开始执行</el-button> -->
|
||||
<!-- <el-button @click="stop(device.udid, index)">停止</el-button> -->
|
||||
<div></div>
|
||||
<!-- <el-button @click="wsActions.isVideoAndLive(device.udid, index)">判断视频还是直播</el-button> -->
|
||||
|
||||
</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)">
|
||||
|
||||
<div class="video-canvas">
|
||||
<video :ref="(el) => (videoElement[device.udid] = el)" autoplay muted playsinline
|
||||
:style="getVideoStyle(index)" @click.stop="selectedDeviceFun(index)"></video>
|
||||
|
||||
: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)">
|
||||
@@ -106,49 +95,43 @@
|
||||
<!-- <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>
|
||||
<!-- <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>
|
||||
<!-- <el-button @click="showDialog = true; dialogTitle = '私信';">导入私信</el-button> -->
|
||||
<div></div>
|
||||
<el-button @click="getComArr(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.clickCopyList(device.udid, index)">获取聊天记录</el-button>
|
||||
<el-button @click="wsActions.getSize(device.udid, index)">获取屏幕尺寸</el-button>
|
||||
|
||||
<!-- <el-button @click="wsActions.clickMesage(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 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>
|
||||
</div>
|
||||
<el-button @click="wsActions.test(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>
|
||||
</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> -->
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button @click="openShowChat = !openShowChat">聊天</el-button>
|
||||
<ChatDialog :visible="openShowChat" leftMsg="123123" rightMsg="safdgasdfasdfasgasedyr5q3245214632452345tsdfgasdf"
|
||||
@close="show = false" />
|
||||
|
||||
<!-- <ChatDialog :visible="openShowChat" :leftMsg="chatContent.left" :rightMsg="chatContent.right"
|
||||
@close="show = false" /> -->
|
||||
<!-- <el-button @click="openShowChat = !openShowChat">聊天</el-button> -->
|
||||
<ChatDialog :visible="openShowChat" :messages="chatList" />
|
||||
</div>
|
||||
|
||||
<MultiLineInputDialog v-model:visible="showDialog" :initialText='""' :title="dialogTitle" :index="selectedDevice"
|
||||
@confirm="onDialogConfirm" @cancel="onDialogCancel" />
|
||||
@confirm="onDialogConfirm" />
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -161,26 +144,24 @@ 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, ElLoading } from 'element-plus'
|
||||
import { chat } from "@/api/chat";
|
||||
import { chat, translation } from "@/api/chat";
|
||||
import MultiLineInputDialog from '@/components/MultiLineInputDialog.vue'; // 根据实际路径修改
|
||||
import ChatDialog from '@/components/ChatDialog.vue'
|
||||
|
||||
import { splitArray } from '@/utils/arrUtil'
|
||||
import { chooseFile } from '@/utils/fileUtil'
|
||||
const router = useRouter();
|
||||
let wsActions = null;
|
||||
|
||||
// 引入刷新方法
|
||||
const reload = inject("reload")
|
||||
let refresh = ref(true);
|
||||
|
||||
let phone = ref({ width: 207, height: 470 });
|
||||
const openStr = base64ToBinary("ZQBwAAAAAAA8CgLQAtAAAAAAAAAAAAD/AAAAAAAAAAAAAAAA"); //开启视频流的启动命令
|
||||
const eitwo = base64ToBinary("BAIAAABHVFJD"); //开启设备信息的命令
|
||||
let isshow = ref(true);
|
||||
let isshow = ref(true); //页面是否隐藏
|
||||
let playTimer = ref([{}, {}, {}, {}, {}, {}, {}, {}]); // 播放定时器
|
||||
let isdown = ref(false);
|
||||
const videoElement = ref({});
|
||||
let deviceInformation = ref([]);
|
||||
|
||||
let isdown = ref(false); //是否是按下鼠标状态
|
||||
const videoElement = ref({}); //视频流元素DOM
|
||||
let deviceInformation = ref([]); //设备信息列表
|
||||
//当前弹窗类型
|
||||
let dialogTitle = ref('');
|
||||
//评论文本内容
|
||||
@@ -193,13 +174,7 @@ let hostIdContentArr = ref([[], [], [], [], [], [], [], [], []]);
|
||||
let textContentpri = ref(['', '', '', '', '', '', '', '']);
|
||||
let textContentpriArr = ref([[], [], [], [], [], [], [], [], []]);
|
||||
//保存聊天内容
|
||||
let chatList = ref([{}, {}, {}, {}, {}, {}, {}, {}]);
|
||||
//传入弹窗的聊天内容
|
||||
let chatContent = ref({
|
||||
left: '',
|
||||
right: ''
|
||||
});
|
||||
|
||||
let chatList = ref([]);
|
||||
//选中设备
|
||||
let selectedDevice = ref(999);
|
||||
//ws列表
|
||||
@@ -234,10 +209,9 @@ const mouseData = {
|
||||
};
|
||||
//打开聊天窗口的状态
|
||||
let openShowChat = ref(false);
|
||||
|
||||
let istranslate = ref(false); //是否是翻译本页
|
||||
let phoneXYinfo = ref(getphoneXYinfo() == null ? [{}, {}, {}, {}, {}, {}, {}, {}] : getphoneXYinfo());
|
||||
console.log('phoneXYinfo.value', phoneXYinfo.value)
|
||||
|
||||
const wsCache = new Map();
|
||||
//``````````````````````````````````````````````````````````````````````````````````
|
||||
// 初始化 手机显示WebSocket 和视频流
|
||||
@@ -269,10 +243,8 @@ const initVideoStream = (udid, index) => {
|
||||
);
|
||||
wslist[index].binaryType = "arraybuffer";
|
||||
|
||||
|
||||
wslist[index].onopen = () => {
|
||||
console.log("手机显示ws已开启");
|
||||
|
||||
wsActions = createWsActions(wslist, isStopLike);
|
||||
// 发送 开启 视频流数据
|
||||
setTimeout(() => {
|
||||
@@ -285,13 +257,10 @@ const initVideoStream = (udid, index) => {
|
||||
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') {
|
||||
if (isStopLike.value[index]) {
|
||||
@@ -302,7 +271,6 @@ const initVideoStream = (udid, index) => {
|
||||
//成功处理
|
||||
console.log('自定义返回', resData)
|
||||
if (resData.status === 'success') {
|
||||
|
||||
//触发长按该位置
|
||||
if (resData.type == 'clickCopy') {
|
||||
console.log('长按', resData.x * iponeCoefficient.value[index].width, resData.y * iponeCoefficient.value[index].height, index)
|
||||
@@ -325,31 +293,34 @@ const initVideoStream = (udid, index) => {
|
||||
wsActions.clickMesage(deviceInformation.value[index].udid, index) //点击消息进入对话框
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
} else if (resData.type == 'clickMesage') {
|
||||
wsActions.clickCopyList(deviceInformation.value[index].udid, index)
|
||||
|
||||
} else if (resData.type == 'isVideoAndLive') {
|
||||
console.log(resData.message)
|
||||
|
||||
} else if (resData.type == 'clickCopyList') { //获取到的消息列表
|
||||
//打印所有信息
|
||||
console.log('消息列表', resData.message)
|
||||
chatList.value = resData.message
|
||||
getTranslation(chatList.value)
|
||||
const mesBox = resData.message[resData.message.length - 1]
|
||||
//打印最新一条信息
|
||||
console.log('最新消息', mesBox)
|
||||
chat({ msg: mesBox.text }).then(res => {
|
||||
console.log(res)
|
||||
chatList.value[index].leftMsg = res.data.translationResult
|
||||
chatList.value[index].rightMsg = res.data.chineseResult
|
||||
// textContentpri.value[index] = res.data.finalResult
|
||||
// PrivatetexToPrivatePush(deviceInformation.value[index].udid, index)
|
||||
})
|
||||
console.log("翻译", istranslate.value)
|
||||
if (istranslate.value == false) {
|
||||
console.log("执行ai")
|
||||
chat({ msg: mesBox.text }).then(res => {
|
||||
console.log("ai返回", res)
|
||||
textContentpri.value[index] = res
|
||||
PrivatetexToPrivatePush(deviceInformation.value[index].udid, index)
|
||||
})
|
||||
} else {
|
||||
console.log("翻译本页")
|
||||
istranslate.value = false
|
||||
}
|
||||
} else if (resData.action == 'getSize') {
|
||||
console.log(iponeCoefficient.value, '手机尺寸宽度:', resData.width, '高度:', resData.height);
|
||||
iponeCoefficient.value[index].width = 320 / resData.width
|
||||
iponeCoefficient.value[index].height = 720 / resData.height
|
||||
|
||||
console.log('尺寸系数', iponeCoefficient.value[index])
|
||||
} else {
|
||||
console.log(resData.type, '坐标返回:x:', resData.x, 'y:', resData.y);
|
||||
@@ -358,7 +329,6 @@ const initVideoStream = (udid, 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 (runType.value[index] == 'follow') {
|
||||
wsActions.slideDown(deviceInformation.value[index].udid, index)//是否继续下一个视频
|
||||
}
|
||||
@@ -386,7 +356,6 @@ const initVideoStream = (udid, index) => {
|
||||
}, 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 }
|
||||
@@ -409,38 +378,30 @@ const initVideoStream = (udid, index) => {
|
||||
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 (runType.value[index] == 'follow') {
|
||||
runType.value[index] = ''
|
||||
}
|
||||
setTimeout(() => {
|
||||
Back('', index);
|
||||
|
||||
setTimeout(() => {
|
||||
Back('', index);
|
||||
if (runType.value[index] == 'listen') {
|
||||
|
||||
} else {
|
||||
} else if (runType.value[index] == 'like' || runType.value[index] == 'follow') {
|
||||
LikesToLikesToLikes(deviceInformation.value[index].udid, index, 2)
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
}, 1000);
|
||||
|
||||
} 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('无关注', index)
|
||||
Back(deviceInformation.value[index].udid, index)
|
||||
setTimeout(() => {
|
||||
|
||||
console.log('观看视频中', index)
|
||||
randomSeeVideo(deviceInformation.value[index].udid, index) //30-50秒后继续循环任务
|
||||
}, 1000);
|
||||
@@ -459,20 +420,16 @@ const initVideoStream = (udid, index) => {
|
||||
}, 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 {
|
||||
// --------------------------------------------------------------------------报错处理
|
||||
@@ -487,7 +444,6 @@ const initVideoStream = (udid, index) => {
|
||||
setTimeout(() => {
|
||||
Back('', index)
|
||||
LikesToLikesToLikes(deviceInformation.value[index].udid, index, 2)
|
||||
|
||||
}, 1000)
|
||||
}, 1000)
|
||||
} else {
|
||||
@@ -497,7 +453,6 @@ const initVideoStream = (udid, index) => {
|
||||
Back('', index)
|
||||
setTimeout(() => {
|
||||
wsActions.isHost(deviceInformation.value[index].udid, index)
|
||||
|
||||
}, 1000)
|
||||
}, 1000)
|
||||
}
|
||||
@@ -525,24 +480,17 @@ const initVideoStream = (udid, index) => {
|
||||
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) {
|
||||
@@ -564,20 +512,16 @@ const initVideoStream = (udid, index) => {
|
||||
|
||||
// 配置参数
|
||||
let canvasRef = ref({});
|
||||
|
||||
// 初始化画布
|
||||
const initCanvas = (udid) => {
|
||||
const canvas = canvasRef.value[udid];
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
|
||||
canvas.style.width = `${phone.value.width * 1.4}px`;
|
||||
canvas.style.height = `${phone.value.height * 1.4}px`;
|
||||
canvas.width = phone.value.width * 1.4 * dpr;
|
||||
canvas.height = phone.value.height * 1.4 * dpr;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.scale(dpr, dpr);
|
||||
|
||||
// 绘制参考网格(可选)
|
||||
ctx.strokeStyle = "#ffffff00";
|
||||
for (let x = 0; x <= phone.value.width; x += 100) {
|
||||
@@ -619,7 +563,6 @@ const handleCanvasup = (udid, event, index) => {
|
||||
mouseData.position.point.x = x;
|
||||
mouseData.position.point.y = y;
|
||||
// console.log(mouseData);
|
||||
|
||||
wslist[index].send(toBuffer(mouseData));
|
||||
};
|
||||
|
||||
@@ -686,7 +629,6 @@ const handleVisibilityChange = () => {
|
||||
playTimer.value.forEach(Timer => {
|
||||
clearInterval(Timer);
|
||||
});
|
||||
|
||||
playTimer.value = [{}, {}, {}, {}, {}, {}, {}, {}];
|
||||
}
|
||||
console.log("页面被隐藏");
|
||||
@@ -697,7 +639,6 @@ const handleVisibilityChange = () => {
|
||||
setTimeout(() => {
|
||||
isshow.value = true;
|
||||
// ObtainDeviceInformation();
|
||||
|
||||
}, 500);
|
||||
|
||||
}
|
||||
@@ -707,14 +648,12 @@ const handleVisibilityChange = () => {
|
||||
onMounted(() => {
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
ObtainDeviceInformation();
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
console.log('触发按键了 键盘事件有效', e)
|
||||
if (e.key == 'Backspace') {
|
||||
key(selectedDevice.value, 'down', 67)
|
||||
}
|
||||
})
|
||||
|
||||
window.addEventListener('keyup', (e) => {
|
||||
// console.log('触发按键了 键盘事件有效抬起', e.keyCode, e.key)
|
||||
if (e.key == 'Backspace') {
|
||||
@@ -722,7 +661,6 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '初始化中...',
|
||||
@@ -756,31 +694,24 @@ const ObtainDeviceInformation = () => {
|
||||
const data = JSON.parse(new TextDecoder('utf-8').decode(event.data).replace(/[^\x20-\x7F]/g, ''));
|
||||
try {
|
||||
console.log('数组', data)
|
||||
|
||||
|
||||
if (data.type == "devicelist") {
|
||||
deviceInformation.value = [];
|
||||
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);
|
||||
setTimeout(() => {
|
||||
wsActions.getSize(item.udid, index)
|
||||
|
||||
}, 2000)
|
||||
}, 300);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
} else if (data.type == "device") {
|
||||
if (data.data.device.state === "offline") {
|
||||
//监听设备信息,出现离线设备,则删除设备信息
|
||||
@@ -810,7 +741,6 @@ const ObtainDeviceInformation = () => {
|
||||
}
|
||||
})
|
||||
} else if (data.data.device.state === "device") {
|
||||
|
||||
let isrepeat = false;
|
||||
//监听设备信息,出现新设备,则添加设备信息
|
||||
deviceInformation.value.forEach((item, index) => {
|
||||
@@ -818,14 +748,12 @@ const ObtainDeviceInformation = () => {
|
||||
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 {
|
||||
@@ -837,7 +765,6 @@ const ObtainDeviceInformation = () => {
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -854,10 +781,9 @@ async function LikesToCommentToComPush(udid, index) {
|
||||
await sendWsTask(index, { udid, action: 'click', type: 'ComPush', index, resourceId: 'com.zhiliaoapp.musically:id/bqg' });
|
||||
}
|
||||
|
||||
|
||||
//点赞主页4个作品+评论最后一个作品并返回
|
||||
async function LikesToLikesToLikes(udid, index, type) {
|
||||
|
||||
isStopLike.value[index] = false;
|
||||
runType.value[index] = 'follow';
|
||||
if (type == 2) {
|
||||
await sendWsTask(index, { udid, action: 'click', type: 'searchTxt', index, resourceId: 'com.zhiliaoapp.musically:id/f0l' });
|
||||
@@ -893,7 +819,6 @@ function setComText(index) {
|
||||
isSend.value = true;
|
||||
setTimeout(() => {
|
||||
isSend.value = false;
|
||||
|
||||
}, 300);
|
||||
console.log('发送评论内容', index, textContent.value[index])
|
||||
wslist[index].send(setClipboard(textContent.value[index]));
|
||||
@@ -905,11 +830,9 @@ function setHostId(index) {
|
||||
isSend.value = true;
|
||||
setTimeout(() => {
|
||||
isSend.value = false;
|
||||
|
||||
}, 300);
|
||||
console.log('发送主播id内容', index, hostIdContent.value[index])
|
||||
wslist[index].send(setClipboard(hostIdContent.value[index])); //发送内容
|
||||
|
||||
//获取当前主播ID的下标
|
||||
const indexBom = hostIdContentArr.value[index].indexOf(hostIdContent.value[index]) + 1;
|
||||
console.log(hostIdContentArr.value[index].indexOf(hostIdContent.value[index]) + 1, '当前主播下标');
|
||||
@@ -920,7 +843,6 @@ function setHostId(index) {
|
||||
hostIdContent.value[index] = ''
|
||||
return
|
||||
}
|
||||
|
||||
hostIdContent.value[index] = hostIdContentArr.value[index][indexBom];
|
||||
console.log(hostIdContent.value[index], '下次搜索')
|
||||
}
|
||||
@@ -930,17 +852,14 @@ function setPrivateText(index) {
|
||||
isSend.value = true;
|
||||
setTimeout(() => {
|
||||
isSend.value = false;
|
||||
|
||||
}, 300);
|
||||
console.log('发送私信内容', index, textContentpri.value[index])
|
||||
wslist[index].send(setClipboard(textContentpri.value[index]));
|
||||
textContentpri.value[index] = textContentpriArr.value[index][getRandomNumber(textContentpriArr.value[index].length - 1)];
|
||||
|
||||
}
|
||||
//获取手机粘贴板方法
|
||||
function getText(index) {
|
||||
wslist[index].send(getClipboard());
|
||||
|
||||
}
|
||||
|
||||
function getComArr(index, type) {
|
||||
@@ -959,7 +878,6 @@ function getComArr(index, type) {
|
||||
function clickxy(x, y, index, type) {
|
||||
console.log('clickxy方法', x, y)
|
||||
if (type == 3) { //关注/私信 后的返回和下滑
|
||||
|
||||
mouseData.action = 0;
|
||||
mouseData.pressure = 1;
|
||||
mouseData.buttons = 1;
|
||||
@@ -982,7 +900,6 @@ function clickxy(x, y, index, type) {
|
||||
}, 300)
|
||||
}, 300)
|
||||
} else if (type == 2) { //评论过后的返回和右滑
|
||||
|
||||
mouseData.action = 0;
|
||||
mouseData.pressure = 1;
|
||||
mouseData.buttons = 1;
|
||||
@@ -1001,7 +918,6 @@ function clickxy(x, y, index, type) {
|
||||
}, 300)
|
||||
}, 300)
|
||||
} else if (type == 1) {//评论框点击后的发送内容
|
||||
|
||||
mouseData.action = 0;
|
||||
mouseData.pressure = 1;
|
||||
mouseData.buttons = 1;
|
||||
@@ -1029,7 +945,6 @@ function clickxy(x, y, index, type) {
|
||||
mouseData.action = 1;
|
||||
wslist[index].send(toBuffer(mouseData));
|
||||
console.log('抬起按下')
|
||||
|
||||
}, 1500)
|
||||
} else {
|
||||
mouseData.action = 0;
|
||||
@@ -1043,7 +958,6 @@ function clickxy(x, y, index, type) {
|
||||
wslist[index].send(toBuffer(mouseData));
|
||||
}, 100)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//创建任务实例
|
||||
@@ -1051,7 +965,6 @@ function createTaskQueue(index) {
|
||||
if (!taskQueues.has(index)) {
|
||||
taskQueues.set(index, []);
|
||||
}
|
||||
|
||||
return {
|
||||
enqueue(task) {
|
||||
taskQueues.get(index).push(task);
|
||||
@@ -1077,7 +990,6 @@ function sendWsTask(index, data) {
|
||||
console.log('发送任务', data.type);
|
||||
return new Promise((resolve) => {
|
||||
const queue = createTaskQueue(index);
|
||||
|
||||
const task = () => {
|
||||
//发送评论的文本粘贴事件
|
||||
if (data.type == 'Likes') {
|
||||
@@ -1090,19 +1002,16 @@ function sendWsTask(index, data) {
|
||||
if (runType.value[index] == 'follow') {
|
||||
clickxy(160, 360, index)
|
||||
}
|
||||
|
||||
}
|
||||
if (data.type == 'ComPush') {
|
||||
setTimeout(() => {
|
||||
setComText(index)//粘贴内容
|
||||
}, 500)
|
||||
|
||||
}
|
||||
if (data.type == 'searchHost') {
|
||||
setTimeout(() => {
|
||||
setHostId(index)//粘贴内容
|
||||
}, 500)
|
||||
|
||||
}
|
||||
//发送私信的文本粘贴事件
|
||||
if (data.type == 'PrivatePush') {
|
||||
@@ -1116,7 +1025,6 @@ function sendWsTask(index, data) {
|
||||
// wsActions.slideRight(data.udid, index)
|
||||
// }, 500);
|
||||
// }, 500);
|
||||
|
||||
}
|
||||
//发送关注之前的返回
|
||||
if (data.type == 'addHost') {
|
||||
@@ -1128,7 +1036,6 @@ function sendWsTask(index, data) {
|
||||
// }, 1000);
|
||||
// }, 500);
|
||||
}
|
||||
|
||||
//发送任务
|
||||
console.log('发送任务', data);
|
||||
if (data.type == 'Attention') {
|
||||
@@ -1143,7 +1050,6 @@ function sendWsTask(index, data) {
|
||||
// 表示当前任务“已发出”,但不是“已完成”
|
||||
// 实际完成由 onmessage 中的 success 决定并继续执行队列
|
||||
};
|
||||
|
||||
queue.enqueue(task);
|
||||
});
|
||||
}
|
||||
@@ -1164,7 +1070,6 @@ function randomSeeVideo(udid, index) {
|
||||
setTimeout(() => {
|
||||
console.log('观看结束', index);
|
||||
wsActions.isHost(udid, index)//检测
|
||||
|
||||
}, delay);
|
||||
}
|
||||
|
||||
@@ -1173,10 +1078,8 @@ 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',
|
||||
border: isSelected ? '2px solid blue' : '1px solid blue',
|
||||
@@ -1186,35 +1089,20 @@ function getVideoStyle(index) {
|
||||
zIndex: isSelected ? 1000 : 1,
|
||||
pointerEvents: isSelected ? 'none' : 'auto',
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function stop(udid, index) {
|
||||
// actions[index] = [];
|
||||
createTaskQueue(index).clear();//清除队伍中的任务
|
||||
cloesMonitor();
|
||||
isStopLike.value.forEach((item, i) => {
|
||||
isStopLike.value[i] = true;
|
||||
runType.value[index] = ''
|
||||
})
|
||||
console.log('停止', isStopLike.value);
|
||||
}
|
||||
|
||||
|
||||
//刷新页面方法
|
||||
function reloadfun() {
|
||||
reload()
|
||||
}
|
||||
|
||||
// //返回次数
|
||||
// function repeatBack(index, times, delay = 1000) {
|
||||
// if (typeof times !== 'number' || times <= 0) return;
|
||||
// for (let i = 1; i <= times; i++) {
|
||||
// setTimeout(() => {
|
||||
// Back('', index);
|
||||
// }, i * delay);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
function openTk() {
|
||||
deviceInformation.value.forEach((device, index) => {
|
||||
wsActions.open(device.udid, index)
|
||||
@@ -1227,7 +1115,6 @@ function openMonitor() {
|
||||
wsActions.getmesNum(device.udid, index)
|
||||
isStopLike.value[index] = false;
|
||||
runType.value[index] = 'listen'
|
||||
|
||||
})
|
||||
isShowMes.value = setInterval(() => {
|
||||
deviceInformation.value.forEach((device, index) => {
|
||||
@@ -1236,6 +1123,7 @@ function openMonitor() {
|
||||
})
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
//关闭监听
|
||||
function cloesMonitor() {
|
||||
deviceInformation.value.forEach((device, index) => {
|
||||
@@ -1247,19 +1135,13 @@ function cloesMonitor() {
|
||||
|
||||
//一键养号
|
||||
function parentNum() {
|
||||
|
||||
deviceInformation.value.forEach((device, index) => {
|
||||
isStopLike.value[index] = false;
|
||||
|
||||
runType.value[index] = 'like'
|
||||
wsActions.isHost(device.udid, index)
|
||||
})
|
||||
}
|
||||
|
||||
//取消弹窗
|
||||
function onDialogCancel() {
|
||||
|
||||
}
|
||||
|
||||
//确认多行文本框内容
|
||||
function onDialogConfirm(result, type, index) {
|
||||
console.log(result, type, index);
|
||||
@@ -1296,7 +1178,6 @@ function onDialogConfirm(result, type, index) {
|
||||
deviceInformation.value.forEach((device, indexB) => {
|
||||
LikesToLikesToLikes(device.udid, indexB, 1)
|
||||
})
|
||||
|
||||
} else {
|
||||
textContentpriArr.value[index] = result;
|
||||
textContentpri.value[index] = result[getRandomNumber(result.length - 1)];
|
||||
@@ -1310,7 +1191,6 @@ function onDialogConfirm(result, type, index) {
|
||||
hostIdContentArr.value[indexA] = hostIdArrList[indexA];
|
||||
hostIdContent.value[indexA] = hostIdContentArr.value[indexA][0];
|
||||
})
|
||||
|
||||
//打开评论弹窗
|
||||
selectedDevice.value = 998;
|
||||
dialogTitle.value = '评论';
|
||||
@@ -1327,183 +1207,19 @@ function onDialogConfirm(result, type, index) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//分割数组
|
||||
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;
|
||||
}
|
||||
function selectedDeviceFun(index) {
|
||||
selectedDevice.value = index
|
||||
chatContent.value.left = chatList.value[index].leftMsg
|
||||
chatContent.value.right = chatList.value[index].rightMsg
|
||||
console.log(chatList.value);
|
||||
console.log(chatContent.value);
|
||||
function getTranslation(list) {
|
||||
list.forEach((item, index) => {
|
||||
translation({ msg: item.text }).then(res => {
|
||||
console.log(res);
|
||||
chatList.value[index].text = res
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
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;
|
||||
}
|
||||
@import '../static/css/video.less';
|
||||
</style>
|
||||
|
||||
@@ -18,6 +18,9 @@ module.exports = defineConfig({
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
less: {
|
||||
additionalData: `@import "@/static/css/app.less";` // 注入全局变量文件
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user