上传代码

This commit is contained in:
pengxiaolong
2025-07-01 21:22:43 +08:00
parent 560581f1a4
commit 01e9c26821
7 changed files with 572 additions and 317 deletions

View File

@@ -1,13 +1,12 @@
import { getAxios, postAxios, downFile } from '@/utils/axios.js' import { getAxios, postAxios, downFile } from '@/utils/axios.js'
//租户获取登录id
export function rentgetloginID(data) {
export function getIdByName(name) { return getAxios({ url: `/api/tenant/get-id-by-name?name=${data.name}`})
return getAxios({ url: `/api/tenant/get-id-by-name?name=${name}` })
} }
//登录
export function login(data) { export function login(data) {
return postAxios({ url: '/api/user/doLogin', data }) return postAxios({ url: '/api/user/bigbrother-doLogin', data })
} }
//获取国家 //获取国家
export function getCountryinfo(data) { export function getCountryinfo(data) {
@@ -20,7 +19,7 @@ export function tkaccountuseinfo(accountName) {
} }
export function tkhostdata(data) { export function tkhostdata(data) {
return postAxios({ url: '/api/save_data/hosts_info', data }) return postAxios({ url: '/api/big-brother/page', data })
} }

View File

@@ -19,11 +19,12 @@ const routes = [
name: 'hostsList', name: 'hostsList',
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/hostsList.vue') component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/hostsList.vue')
}, },
{ // {
path: 'workBenches', // path: 'workBenches',
name: 'workBenches', // name: 'workBenches',
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/workbenches.vue') // component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/workbenches.vue')
},] // },
]
} }
] ]
const router = createRouter({ const router = createRouter({

View File

@@ -17,13 +17,14 @@ let baseURL = ''
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
// 生产环境 // 生产环境
// baseURL = "https://api.tkpage.yolozs.com" // baseURL = "https://api.tkpage.yolozs.com"
baseURL = "http://192.168.1.174:8101" baseURL = "http://47.79.98.113:8101"
// baseURL = "http://192.168.0.103:8085/" // baseURL = "http://192.168.0.103:8085/"
} else { } else {
// 测试环境 // 测试环境
// baseURL = "http://120.26.251.180:8085/" // baseURL = "http://120.26.251.180:8085/"
// 开发环境 // 开发环境
baseURL = "https://api.tkpage.yolozs.com" // baseURL = "https://api.tkpage.yolozs.com"
baseURL = "http://47.79.98.113:8101"
// baseURL = "http://api.tkpage.vvtiktok.cn" // baseURL = "http://api.tkpage.vvtiktok.cn"
} }
@@ -32,7 +33,7 @@ axios.interceptors.request.use((config) => {
console.log("config", config) console.log("config", config)
const url = sliceUrl(config.url) const url = sliceUrl(config.url)
console.log("url", url) console.log("url", url)
if (!(config.url == 'doLogin' || config.url == 'get-id-by-name')) { if (!(config.url == 'bigbrother-doLogin' || config.url == 'get-id-by-name')) {
config.headers['vvtoken'] = getToken(); config.headers['vvtoken'] = getToken();
} }
@@ -52,10 +53,14 @@ axios.interceptors.response.use((response) => {
if (response.data.code == 0) { if (response.data.code == 0) {
console.log("response", response.data.data) console.log("response", response.data.data)
return response.data.data return response.data.data
} else { } else if (response.data.code == 40400) {
router.push('/') router.push('/')
ElMessage.error(response.data.code + '' + response.data.message); ElMessage.error(response.data.code + '' + response.data.message);
}else{
ElMessage.error(response.data.code + '' + response.data.message);
} }
}, (error) => { }, (error) => {
// 可添加请求失败后的处理逻辑 // 可添加请求失败后的处理逻辑

View File

@@ -1,11 +1,12 @@
// pythonBridge.js // pythonBridge.js
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
const bridge = ref(null); import { ElMessage } from 'element-plus';
const pyBridge = ref(null);
// 初始化 QWebChannel // 初始化 QWebChannel
const initBridge = () => { const initBridge = () => {
if (/localhost/.test(window.location.href)) return if (/localhost/.test(window.location.href)) return
new QWebChannel(qt.webChannelTransport, (channel) => { new QWebChannel(qt.webChannelTransport, (channel) => {
bridge.value = channel.objects.bridge; pyBridge.value = channel.objects.bridge;
}); });
}; };
export function usePythonBridge() { export function usePythonBridge() {
@@ -13,95 +14,123 @@ export function usePythonBridge() {
// 调用 Python 方法 // // 调用 Python 方法
const fetchDataConfig = (data) => { // const fetchDataConfig = (data) => {
// return new Promise((resolve, reject) => {
// if (bridge.value) {
// bridge.value.fetchDataConfig(data, function (result) {
// resolve(result);
// });
// }
// });
// };
// // 查询获取主播的数据
// const fetchDataCount = () => {
// return new Promise((resolve, reject) => {
// if (bridge.value) {
// bridge.value.fetchDataCount(function (result) {
// resolve(result);
// });
// }
// });
// };
// 查询获取大哥的数据
const controlTask = (data) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (bridge.value) { if (pyBridge.value) {
bridge.value.fetchDataConfig(data, function (result) { pyBridge.value.control_task(data,function (result) {
resolve(result); resolve(result);
}); });
}else{
console.log("pyBridge is null未连接上")
} }
}); });
}; };
// 查询获取主播的数据 //总数有效数
const fetchDataCount = () => { const getBrotherInfo = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (bridge.value) { if (pyBridge.value) {
bridge.value.fetchDataCount(function (result) { pyBridge.value.getBrotherInfo(function (result) {
resolve(result); resolve(JSON.parse(result));
// ElMessage.success(result);
}); });
}else{
console.log("pyBridge is null未连接上")
} }
}); });
}; };
// 打开tk后台 // 打开tk后台
const loginTikTok = () => { const loginTikTok = () => {
if (bridge.value) { if (pyBridge.value) {
bridge.value.loginTikTok(function (result) { pyBridge.value.loginTikTok(function (result) {
}); });
} }else{
console.log("pyBridge is null未连接上")
};
// 登录tk后台
const loginBackStage = (data) => {
if (bridge.value) {
if (data.index == 0) {
bridge.value.loginBackStage(JSON.stringify(data));
} else if (data.index == 1) {
bridge.value.loginBackStageCopy(JSON.stringify(data));
}
} }
}; };
// // 登录tk后台
// const loginBackStage = (data) => {
// if (bridge.value) {
// if (data.index == 0) {
// bridge.value.loginBackStage(JSON.stringify(data));
// } else if (data.index == 1) {
// bridge.value.loginBackStageCopy(JSON.stringify(data));
// }
// }
// };
//跳转到主播页面 //跳转到主播页面
const givePyAnchorId = (id) => { const givePyAnchorId = (id) => {
console.log("id",id);
if (bridge.value) { if (pyBridge.value) {
bridge.value.givePyAnchorId(id, function (result) { ElMessage.success(id);
pyBridge.value.givePyAnchorId(id, function (result) {
}); });
} }
}; };
//查询登录状态 // //查询登录状态
const backStageloginStatus = () => { // const backStageloginStatus = () => {
return new Promise((resolve, reject) => { // return new Promise((resolve, reject) => {
if (bridge.value) { // if (bridge.value) {
bridge.value.backStageloginStatus(function (result) { // bridge.value.backStageloginStatus(function (result) {
resolve(result); // resolve(result);
}); // });
} // }
}); // });
}; // };
//查询登录状态 // //查询登录状态
const backStageloginStatusCopy = () => { // const backStageloginStatusCopy = () => {
return new Promise((resolve, reject) => { // return new Promise((resolve, reject) => {
if (bridge.value) { // if (bridge.value) {
bridge.value.backStageloginStatusCopy(function (result) { // bridge.value.backStageloginStatusCopy(function (result) {
resolve(result); // resolve(result);
}); // });
} // }
}); // });
}; // };
//导出表格 //导出表格
const exportToExcel = (data) => { const exportToExcel = (data) => {
if (bridge.value) { if (pyBridge .value) {
bridge.value.exportToExcel(JSON.stringify(data)); pyBridge .value.exportToExcel(JSON.stringify(data));
} }
}; };
const stopScript = () => { const stopScript = () => {
if (bridge.value) { if (pyBridge .value) {
bridge.value.stopScript(); pyBridge .value.stopScript();
} }
}; };
@@ -109,8 +138,8 @@ export function usePythonBridge() {
//获取版本号 //获取版本号
const getVersion = () => { const getVersion = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (bridge.value) { if (pyBridge.value) {
bridge.value.currentVersion(function (result) { pyBridge.value.currentVersion(function (result) {
resolve(result); resolve(result);
}); });
} }
@@ -120,15 +149,12 @@ export function usePythonBridge() {
onMounted(initBridge); onMounted(initBridge);
return { return {
fetchDataConfig,
fetchDataCount,
loginBackStage,
loginTikTok, loginTikTok,
givePyAnchorId,
backStageloginStatus,
backStageloginStatusCopy,
exportToExcel, exportToExcel,
stopScript, stopScript,
getVersion controlTask,
getBrotherInfo,
getVersion,
givePyAnchorId
}; };
} }

View File

@@ -24,10 +24,9 @@
<div class="center-line" style="margin-top: 40px;"> <div class="center-line" style="margin-top: 40px;">
<!-- logo --> <!-- logo -->
<div class="logo"> <div class="logo">
<div class="center-justify" style="height: 80px; width: 300px;"> <!-- <div class="center-justify" style="height: 80px; width: 300px;">
<!-- <img style="margin-right: 20px;height: 100%;" src="@/assets/logo.png"> -->
<img style="height: 100%;" src="@/assets/logotext.png"> <img style="height: 100%;" src="@/assets/logotext.png">
</div> </div> -->
</div> </div>
<!-- From --> <!-- From -->
@@ -38,6 +37,7 @@
<div class="from-input"> <div class="from-input">
<el-form label-position="left" label-width="100px" :model="formData"> <el-form label-position="left" label-width="100px" :model="formData">
<div class="from-input-item1"> <div class="from-input-item1">
<img src="@/assets/username.png" alt=""> <img src="@/assets/username.png" alt="">
<el-input style="height: 25px;" v-model="formData.tenantName" placeholder="租户名称" <el-input style="height: 25px;" v-model="formData.tenantName" placeholder="租户名称"
@@ -74,7 +74,7 @@
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { login, getIdByName } from '@/api/account'; import { login, rentgetloginID } from '@/api/account';
import { getToken, setToken, setUser, setUserPass, getUserPass } from '@/utils/storage'; import { getToken, setToken, setUser, setUserPass, getUserPass } from '@/utils/storage';
import { ElLoading } from 'element-plus'; import { ElLoading } from 'element-plus';
import { usePythonBridge } from '@/utils/pythonBridge' import { usePythonBridge } from '@/utils/pythonBridge'
@@ -82,16 +82,39 @@ import { usePythonBridge } from '@/utils/pythonBridge'
const { getVersion } = usePythonBridge(); const { getVersion } = usePythonBridge();
let version = ref('0.0.0'); let version = ref('0.0.0');
// 测试 localStorage
const testLocalStorage = () => {
try {
// 尝试设置一个测试项
localStorage.setItem('testKey', 'testValue');
// 尝试获取这个测试项
const testValue = localStorage.getItem('testKey');
if (testValue === 'testValue') {
} else {
console.error('localStorage is not working');
ElMessage.error('localStorage 被禁用');
}
} catch (error) {
console.error('localStorage is not available:', error);
ElMessage.error('localStorage 不可用');
}
};
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
getVersion().then((res) => { getVersion().then((res) => {
version.value = res; version.value = res;
}) })
// 测试localStorage;
testLocalStorage();
}, 500); }, 500);
}) })
const router = useRouter(); const router = useRouter();
const formData = ref({ const formData = ref({
@@ -109,11 +132,14 @@ const onSubmit = () => {
background: 'rgba(0, 0, 0, 0.7)', background: 'rgba(0, 0, 0, 0.7)',
}); });
setUserPass(formData.value); setUserPass(formData.value);
getIdByName(formData.value.tenantName).then((tenantId) => { rentgetloginID({
console.log(tenantId) name: formData.value.tenantName,
}).then((res) => {
console.log(res);
login({ login({
tenantId: Number(tenantId),
username: formData.value.userId, username: formData.value.userId,
tenantId: res,
password: formData.value.password, password: formData.value.password,
}).then((res) => { }).then((res) => {
loading.close(); loading.close();
@@ -124,9 +150,11 @@ const onSubmit = () => {
}).catch((err) => { }).catch((err) => {
loading.close(); loading.close();
}); });
})
}).catch((err) => {
loading.close();
console.log(err)
});
}; };
</script> </script>
@@ -203,6 +231,7 @@ const onSubmit = () => {
.logo { .logo {
padding: 20px 0; padding: 20px 0;
height: 80px;
} }
.from { .from {

View File

@@ -1,76 +1,202 @@
<template> <template>
<div class="hostList"> <div class="hostList">
<div> <div>
<div style="display: flex;"> <!-- -->
<el-select v-model="searchForm.country" filterable placeholder="选择国家" size="large" style="width: 160px"> <div style="display: flex">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<div></div> <div></div>
<el-date-picker v-model="searchForm.createTime" type="date" value-format="YYYY-MM-DD" placeholder="选择查询时间" <el-input
size="large" style="margin-left: 50px;width: 160px;" /> v-model="queryFormData.coinMin"
placeholder="最小金币"
size="large"
style="width: 160px;"
type="number"
/>
<el-input v-model="searchForm.hostsId" placeholder="请输入主播id" size="large" <el-input
style="width: 160px; margin-left: 50px;" clearable /> v-model="queryFormData.coinMax"
placeholder="最大金币"
size="large"
style="width: 160px; margin-left: 50px"
type="number"
/>
<el-button class="serch-button" style="margin-left: 50px;" type="primary" @click="serch">查询</el-button> <el-input
<el-button class="put-button" :disabled="tableData.length == 0" type="primary" v-model="queryFormData.levelMin"
@click="exportList">导出Excel数据</el-button> placeholder="最小等级"
<!-- <el-button class="put-button" type="primary" @click="dialogFormVisible = true">分配给指定员工</el-button> --> size="large"
<el-button @click="filterdialogVisible = true" style="width: 50px;" class="put-button" type="primary"><img style="width: 160px; margin-left: 50px"
style="height: 30px;" src="@/assets/filter.png"></el-button> type="number"
/>
<el-input
v-model="queryFormData.levelMax"
placeholder="最大等级"
size="large"
style="width: 160px; margin-left: 50px"
type="number"
/>
<div style="width: 250px; margin-left: 50px;height: 50px;line-height: 50px;">当前网络{{ countryData }}</div>
<div style="width: 160px; margin-left: 50px;height: 50px;line-height: 50px;">总数{{ getBrotherInfodata.total }}</div>
<div style="width: 160px; margin-left: 50px;height: 50px;line-height: 50px;">有效数{{ getBrotherInfodata.valid }}</div>
<el-button
class="serch-button"
style="margin-left: 50px ;"
type="primary"
@click="Resetss"
>重置</el-button
>
<el-button
class="serch-button"
style="margin-left: 50px ; width: 150px"
type="primary"
@click="openTikTok"
>打开 TikTok 登录</el-button
>
<el-button
v-show="queryFormData.isRunning"
class="serch-button"
style="margin-left: 50px"
type="primary"
@click="getBigBrother"
>开始</el-button
>
<el-button
v-show="!queryFormData.isRunning"
class="serch-button"
style="margin-left: 50px"
type="primary"
@click="BigBrotherstop"
>结束</el-button
>
</div> </div>
<!-- `````````````````````````````````````````````````````````````````````````````````````````````````` -->
<div style="width: 100%; border-bottom: 1px solid #e9e9e9; margin-top: 30px"></div>
<!-- ···································································································· -->
<div style="display: flex; margin-top: 30px;flex-wrap: wrap;">
<el-select
v-model="searchForm.region"
filterable
placeholder="选择国家"
size="large"
style="width: 160px;"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-input
v-model="searchForm.displayId"
placeholder="大哥id"
size="large"
style="width: 160px; margin-left: 50px;"
clearable
/>
<el-button
class="serch-button"
style="margin-left: 50px;"
type="primary"
@click="serch"
>查询</el-button
>
<el-button class="serch-button" type="primary" @click="reset"> 重置 </el-button>
<el-button
class="put-button"
:disabled="tableData.length == 0"
type="primary"
@click="exportList"
>导出Excel数据</el-button
>
<el-button @click="filterdialogVisible = true" style="width: 50px;" class="put-button" type="primary"><img
style="height: 30px;" src="@/assets/filter.png"></el-button>
<!-- <el-button @click="filterdialogVisible = true" style="width: 50px;" class="put-button" type="primary"><img
style="height: 30px;" src="@/assets/filter.png"></el-button> -->
</div>
<!-- ····················································································································· -->
<div class="hostTable center-justify"> <div class="hostTable center-justify">
<el-table ref="multipleTableRef" :data="tableData" stripe v-loading="loading" height="500" <el-table
@selection-change="handleSelectionChange"> ref="multipleTableRef"
<el-table-column type="selection" width="35" /> :data="tableData"
stripe
v-loading="loading"
max-height="500"
@selection-change="handleSelectionChange"
>
<!-- <el-table-column type="selection" width="35" /> -->
<el-table-column fixed prop="hostId" label="主播id" width="160"> <el-table-column fixed prop="displayId" label="Id" width="170">
<template #default="scope"> <template #default="scope">
<div class="hostIdText" @click="openHTML(scope.row.hostId)"> {{ <div class="hostIdText" @click="openHTML(scope.row.displayId)">
scope.row.hostId }}</div> {{ scope.row.displayId }}
</template>
</el-table-column>
<el-table-column prop="hostlevel" label="等级" width="80">
<template #default="scope">
{{ scope.row.hostlevel }}
</template>
</el-table-column>
<el-table-column v-for="label in labelList" :key="label.paramCode" :prop="label.paramCode"
:label="label.paramCodeMeaning" width="120">
<template v-if="label.paramCode != 'createDt'" #default="scope">
</template>
</el-table-column>
<!-- <el-table-column label="操作">
<template #default="scope">
<div style="display: flex; align-items: center">
<el-button type="primary" @click="getTkhostdetail(scope.row.hostId)">查看</el-button>
</div> </div>
</template> </template>
</el-table-column> --> </el-table-column>
<el-table-column
v-for="label in labelList"
:key="label.paramCode"
:prop="label.paramCode"
:label="label.paramCodeMeaning"
width="170"
>
<template v-if="label.paramCode != 'createDt'" #default="scope"> </template>
</el-table-column>
</el-table> </el-table>
</div> </div>
<!-- ······································································································································ -->
<!-- 分页 --> <!-- 分页 -->
<div class="center-justify" style="margin-top: 30px;"> <div class="center-justify" style="margin-top: 30px">
<el-pagination v-model:current-page="page" v-model:page-size="pageSize" background <el-pagination
layout="sizes, prev, pager, next" :total="total" :page-sizes="[10, 20, 50, 100]" v-model:current-page="page"
@size-change="handleSizeChange" @current-change="handleCurrentChange" /> v-model:page-size="pageSize"
background
layout="sizes, prev, pager, next"
:total="total"
:page-sizes="[10, 20, 50, 100, 500, 1000]"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div> </div>
</div>
<!-- ·······································································弹窗······································································· -->
<el-dialog v-model="filterdialogVisible" width="800px" :before-close="handleClose">
<el-row :gutter="20">
<el-col :span="4">
<!-- <label>选择筛选条件</label> -->
<div style="height: 100%; padding-top: 10px" class="center-justify">
时间
</div>
</el-col>
<el-col :span="10">
<div><label>开始时间/结束时间</label></div>
<el-date-picker
v-model="createTimes"
type="datetimerange"
value-format="YYYY-MM-DD"
placeholder="选择查询时间"
size="large"
style="width: 600px;margin-top: 10px"
/>
</el-col>
</el-row>
<el-dialog v-model="filterdialogVisible" width="800px" :before-close="handleClose">
<el-row v-for="(field, index) in fields" :key="index" :gutter="20" style="margin-bottom: 10px"> <el-row v-for="(field, index) in fields" :key="index" :gutter="20" style="margin-bottom: 10px">
<el-col :span="4"> <el-col :span="4">
<div style="height: 100%; padding-top: 10px" class="center-justify"> <div style="height: 100%;" class="center-justify">
{{ field.label }} {{ field.label }}
</div> </div>
</el-col> </el-col>
@@ -86,7 +212,6 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="4"> <el-col :span="4">
<!-- <label>选择筛选条件</label> --> <!-- <label>选择筛选条件</label> -->
@@ -99,14 +224,15 @@
<div><label>排序类型</label></div> <div><label>排序类型</label></div>
<el-select v-model="sortData.sortType" filterable placeholder="请选择" style="width: 240px"> <el-select v-model="sortData.sortName" filterable placeholder="请选择" style="width: 240px">
<el-option v-for="item in sortNameOptions" :key="item.type" :label="item.label" :value="item.type" /> <el-option v-for="item in sortNameOptions" :key="item.type" :label="item.label" :value="item.type" />
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<div><label>升序/降序</label></div> <div><label>升序/降序</label></div>
<el-select v-model="sortData.sortForm" filterable placeholder="请选择" style="width: 240px"> <el-select v-model="sortData.sort" filterable placeholder="请选择" style="width: 240px">
<el-option v-for="item in [{ label: '升序', value: 'asc' }, { label: '降序', value: 'desc' }]" :key="item.value" <el-option v-for="item in [{ label: '升序', value: 'asc' }, { label: '降序', value: 'desc' }]" :key="item.value"
:label="item.label" :value="item.value" /> :label="item.label" :value="item.value" />
</el-select> </el-select>
@@ -125,121 +251,202 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
// import { getToken, setToken, removeToken } from '@/utils/storage' // import { getToken, setToken, removeToken } from '@/utils/storage'
import { tkhostdata, dicts, tkhostdetail, downList, getStaffList, managerhosts, upholdinfo, getCountryinfo, accountName } from '@/api/account'; import {
import { usePythonBridge, } from '@/utils/pythonBridge' tkhostdata,
import { getUser, setSerch, getSerch } from '@/utils/storage' dicts,
import { ref, reactive, onMounted } from 'vue'; tkhostdetail,
import EChartsComponent from '@/components/EChartsComponent.vue'; downList,
import { ElMessage, ElMessageBox } from 'element-plus' getStaffList,
import { color } from 'echarts'; managerhosts,
upholdinfo,
getCountryinfo,
accountName,
} from "@/api/account";
import { usePythonBridge} from "@/utils/pythonBridge";
import { getUser, setSerch, getSerch } from "@/utils/storage";
import { ref, reactive, onMounted } from "vue";
import EChartsComponent from "@/components/EChartsComponent.vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { color } from "echarts";
import { getCountryName } from '@/utils/countryUtil'
const loading = ref(false) //ip国家
let countryData = ref('');
//获取国家
const getIpInfo = async () => {
try {
const response = await fetch('https://ipapi.co/json/');
if (!response.ok) {
throw new Error('请求失败');
}
const data = await response.json();
console.log('IP信息:', data.country);
countryData.value = getCountryName(data.country);
} catch (error) {
console.error('请求出错:', error);
ElMessageBox.prompt('请输入将要获取国家的中文名', '获取国家失败', {
confirmButtonText: '确认',
cancelButtonText: '取消',
showClose: false,
closeOnClickModal: false,
showCancelButton: false,
})
.then(({ value }) => {
countryData.value = value
})
// .catch(() => {
// ElMessage({
// type: 'info',
// message: 'Input canceled',
// })
// })
}
};
//打开TikTok登录
function openTikTok() {
loginTikTok();
}
//重置
function Resetss() {
queryFormData.value = {}
}
//大哥climb
const queryFormData = ref({
coinMin: "",
coinMax: "",
levelMin: "",
levelMax: "",
isRunning: true,
});
//时间
const timerId = ref(null)
const getBrotherInfodata = ref({
total: 0,
valid: 0,
})
function BigBrotherstop() {
queryFormData.value.tenantId = userInfo.value.tenantId;
queryFormData.value.region = countryData.value;
controlTask(JSON.stringify(queryFormData.value)).then(res => {
queryFormData.value.isRunning = true;
clearInterval(timerId.value)
timerId.value = null
})
}
function getBigBrother() {
queryFormData.value.tenantId = userInfo.value.tenantId;
queryFormData.value.region = countryData.value;
controlTask(JSON.stringify(queryFormData.value)).then(res => {
queryFormData.value.isRunning = false;
timerId.value = setInterval(() => {
getBrotherInfo().then(res => {
getBrotherInfodata.value = res;
})
}, 1000)
})
}
const loading = ref(false);
//py方法 //py方法
const { givePyAnchorId, exportToExcel } = usePythonBridge(); const { givePyAnchorId, exportToExcel, loginTikTok , controlTask , getBrotherInfo } = usePythonBridge();
let num = ref(0) let num = ref(0);
//账号信息 //账号信息
const userInfo = ref(getUser()) const userInfo = ref(getUser());
//主播列表DOM //主播列表DOM
const multipleTableRef = ref(null) const multipleTableRef = ref(null);
let labelList = ref([ let labelList = ref([
{ paramCode: 'country', paramCodeMeaning: '国家' }, { paramCode: "userIdStr", paramCodeMeaning: "用户id" },
{ paramCode: 'createTime', paramCodeMeaning: '创建时间' }, { paramCode: "level", paramCodeMeaning: "等级" },
{ paramCode: 'hostsCoins', paramCodeMeaning: '主播金币' }, { paramCode: "hostcoins", paramCodeMeaning: "打赏的金币" },
{ paramCode: 'yesterdayCoins', paramCodeMeaning: '昨日金币' }, { paramCode: "totalGiftCoins", paramCodeMeaning: "打赏金币总和" },
{ paramCode: 'fans', paramCodeMeaning: '粉丝数' }, { paramCode: "hostDisplayId", paramCodeMeaning: "所在直播间主播id" },
{ paramCode: 'fllowernum', paramCodeMeaning: '关注数' }, { paramCode: "region", paramCodeMeaning: "地区" },
{ paramCode: 'onlineFans', paramCodeMeaning: '在线粉丝' }, { paramCode: "followerCount", paramCodeMeaning: "粉丝数" },
{ paramCode: 'hostsKind', paramCodeMeaning: '主播类型' }, { paramCode: "followingCount", paramCodeMeaning: "关注数" },
{ paramCode: "createTime", paramCodeMeaning: "创建时间" },
]); ]);
const tableData = ref([])
const tableData = ref([]);
//主播列表传参 //主播列表传参
const searchForm = ref({}) const searchForm = ref({});
const createTimes = ref([]);
//分页
const page = ref(1);
const pageSize = ref(10);
const fields = [ const fields = [
{ label: '粉丝数', minModel: 'fansMin', maxModel: 'fansMax' }, { label: "打赏的金币", minModel: "hostcoinsMin", maxModel: "hostcoinsMax" },
{ label: '在线人数', minModel: 'onlineFansMin', maxModel: 'onlineFansMax' }, { label: "打赏金币总和", minModel: "totalGiftCoinsMin", maxModel: "totalGiftCoinsMax" },
{ label: '金币数', minModel: 'hostsCoinsMin', maxModel: 'hostsCoinsMax' }, { label: "等级", minModel: "levelMin", maxModel: "levelMax" },
{ label: '关注数', minModel: 'fllowernumMin', maxModel: 'fllowernumMax' }, ];
]
//排序 //排序
let sortData = ref({ sortForm: 'desc', sortType: "createTime" }) let sortData = ref({ sortName: "createTime", sort: "desc" });
//排序类型 //排序类型
let sortNameOptions = ref([ let sortNameOptions = ref([
{ label: '创建时间', type: 'createTime' }, { label: "创建时间", type: "createTime" },
{ label: '主播金币', type: 'hostsCoins' }, { label: "打赏的金币", type: "hostsCoins" },
{ label: '粉丝数', type: 'fans' }, { label: "打赏金币总和", type: "totalGiftCoins" },
{ label: '昨日金币', type: 'yesterdayCoins' }, { label: "等级", type: "level" },
{ label: '在线粉丝', type: 'onlineFans' }, ]);
{ label: '关注数', type: 'fllowernum' },
])
//员工选择列表 //员工选择列表
let staffOptions = ref([]) let staffOptions = ref([]);
//筛选条件选择列表 //筛选条件选择列表
//选择的员工 //选择的员工
let staffValue = ref('') let staffValue = ref("");
//选择的主播列表 //选择的主播列表
let selectHostList = ref([]) let selectHostList = ref([]);
//分配弹窗是否弹出 //分配弹窗是否弹出
let dialogFormVisible = ref(false) let dialogFormVisible = ref(false);
//分配情况弹窗是否弹出 //分配情况弹窗是否弹出
let hostNameVisible = ref(false) let hostNameVisible = ref(false);
//备注弹窗是否弹出 //备注弹窗是否弹出
let commentVisible = ref(false) let commentVisible = ref(false);
//筛选弹窗是否弹出 //筛选弹窗是否弹出
let filterdialogVisible = ref(false) let filterdialogVisible = ref(false);
//分配的员工 //分配的员工
let staffId = ref({}) let staffId = ref({});
//备注信息 //备注信息
let commentInfo = ref('') let commentInfo = ref("");
//备注信息主播 //备注信息主播
let commentHost = ref('') let commentHost = ref("");
//分页 //分页
let pageSize = ref(10) let total = ref(0);
let page = ref(1)
let total = ref(0)
//是否渲染 //是否渲染
const isPopoverVisible = reactive({}) const isPopoverVisible = reactive({});
let options = ref([]);
let options = ref([]) let version = ref("0.0.0");
let version = ref('0.0.0');
onMounted(() => { onMounted(() => {
getCountry(); //获取国家 getCountry(); //获取国家
// getSerchStorage();//获取搜索条件 // getSerchStorage();//获取搜索条件
getlist();//获取主播列表 getlist();//获取主播列表
}) getIpInfo();
});
function serch() { function serch() {
page.value = 1 page.value = 1;
getlist(); getlist();
} }
function exportList() {
if (searchForm.value.dataType == 'InvitationType') {
searchForm.value.dataEnd = searchForm.value.dataStart
}
exportToExcel({})
function exportList() {
// if (searchForm.value.dataType == "InvitationType") {
// searchForm.value.dataEnd = searchForm.value.dataStart;
// }
exportToExcel(requestParams.value);
// //浏览器导出方法 // //浏览器导出方法
// downList('export/hostsinfo', // downList('export/hostsinfo',
@@ -251,94 +458,87 @@ function exportList() {
// userId: userInfo.value.userId, // userId: userInfo.value.userId,
// } // }
// ); // );
} }
//分页每页条数 //分页每页条数
function handleSizeChange(val) { function handleSizeChange(val) {
console.log(`${val} items per page`) console.log(`${val} items per page`);
getlist(); getlist();
} }
//分页页数 //分页页数
function handleCurrentChange(val) { function handleCurrentChange(val) {
console.log(`current page: ${val}`) console.log(`current page: ${val}`);
getlist(); getlist();
} }
//选择行 //选择行
function handleSelectionChange(data) { function handleSelectionChange(data) {
console.log(data) console.log(data);
selectHostList.value = [] selectHostList.value = [];
data.forEach(item => { data.forEach((item) => {
selectHostList.value.push(item.hostId) selectHostList.value.push(item.hostId);
}) });
// multipleTableRef.value = data // multipleTableRef.value = data
// console.log(multipleTableRef.value) // console.log(multipleTableRef.value)
}
//时间格式化
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0开始需要+1
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
} }
//获取主播列表 //获取主播列表
//记录请求参数
let requestParams = ref({});
const getlist = () => { const getlist = () => {
loading.value = true;
loading.value = true
console.log(searchForm.value)
tkhostdata({ tkhostdata({
tenantId: Number(userInfo.value.tenantId), tenantId: Number(userInfo.value.tenantId),
sort: sortData.value.sortForm,//正序倒序 sort: sortData.value.sort, //正序倒序
sortName: sortData.value.sortType,//排序类型 sortName: sortData.value.sortName, //排序类型
"current": page.value, current: page.value,
"pageSize": pageSize.value, pageSize: pageSize.value,
...searchForm.value,//筛选条件 createTimeStart:createTimes.value[0],
}).then(res => { createTimeEnd:createTimes.value[1],
loading.value = false ...searchForm.value, //筛选条件
}).then((res) => {
loading.value = false;
console.log(res);
if (res) { if (res) {
console.log('主播列表', res) requestParams.value = res.records;
total.value = Number(res.total) console.log(res.records);
tableData.value = res.records.map(item => ({ total.value = Number(res.total);
hostId: item.hostsId, // 注意:原字段是 hostId你的数据是 hostsId需手动映射 tableData.value = res.records.map((item) => ({
hostlevel: item.hostsLevel, // 原字段 hostlevel 对应你的数据 hostsLevel level: item.level,// 等级
country: item.country, createTime:formatDate(new Date(item.createTime)),// 创建时间
createTime: item.createTime, followerCount: item.followerCount,// 粉丝数
fans: item.fans, followingCount: item.followingCount,// 关注数
fllowernum: item.fllowernum, hostDisplayId: item.hostDisplayId,// 所在直播间主播id
hostsCoins: item.hostsCoins, hostcoins: item.hostcoins,// 打赏的金币
hostsKind: item.hostsKind, region: item.region,// 地区
onlineFans: item.onlineFans, totalGiftCoins: item.totalGiftCoins,// 打赏金币总和
yesterdayCoins: item.yesterdayCoins, userIdStr: item.userIdStr,// 用户id
// 保留原有字段(如 belongBy、useable 等) displayId: item.displayId,
belongBy: item.belongBy,
useable: item.useable
})); }));
} }
});
};
})
}
function handelClick() { function handelClick() {
filterdialogVisible.value = false filterdialogVisible.value = false;
} }
function reset() { function reset() {
searchForm.value.fansMin = null searchForm.value = {}
searchForm.value.fansMax = null sortData.value = { sortName: "createTime", sort: "desc" }
searchForm.value.onlineFansMin = null createTimes.value = []
searchForm.value.onlineFansMax = null
searchForm.value.hostsCoinsMin = null
searchForm.value.hostsCoinsMax = null
searchForm.value.fllowernumMin = null
searchForm.value.fllowernumMax = null
} }
function handleClose(done) { function handleClose(done) {
console.log('关闭') console.log("关闭");
// searchForm.value = { done();
// dataType: '',
// dataStart: '',
// dataEnd: '',
// }
done()
} }
//修改主播维护状态 //修改主播维护状态
// function handleSelectChange(event, data) { // function handleSelectChange(event, data) {
@@ -369,25 +569,28 @@ function handleClose(done) {
// } // }
function filterTag(value, row) { function filterTag(value, row) {
console.log(row.useable, value) console.log(row.useable, value);
return row.useable === value; return row.useable === value;
} }
//获取国家 //获取国家
function getCountry() { function getCountry() {
getCountryinfo({}).then(res => { getCountryinfo({})
console.log(res) .then((res) => {
res.forEach(item => { console.log('````````国家`````````',res);
if (item.countryGroupName) { res.forEach((item) => {
options.value.push({ value: item.countryGroupName, label: item.countryGroupName }) if (item.countryGroupName) {
options.value.push({
} value: item.countryGroupName,
label: item.countryGroupName,
});
}
});
console.log('````````国家2`````````', options.value);
}) })
console.log(options.value) .catch((err) => {
}).catch(err => { console.log("getCountry", err);
console.log('getCountry', err) });
})
} }
//获取下级员工 //获取下级员工
@@ -407,7 +610,6 @@ function getCountry() {
// }) // })
// } // }
// //分配主播给员工 // //分配主播给员工
// function allocation() { // function allocation() {
// managerhosts({ // managerhosts({
@@ -423,7 +625,6 @@ function getCountry() {
// }) // })
// } // }
//获取主播信息 //获取主播信息
// const getTkhostdetail = (id) => { // const getTkhostdetail = (id) => {
// tkhostdetail({ // tkhostdetail({
@@ -439,22 +640,18 @@ function getCountry() {
// } // }
function openPopover(hostId, paramCode) { function openPopover(hostId, paramCode) {
isPopoverVisible[`${hostId}-${paramCode}`] = true; isPopoverVisible[`${hostId}-${paramCode}`] = true;
} }
function closePopover(hostId, paramCode) { function closePopover(hostId, paramCode) {
// isPopoverVisible[`${hostId}-${paramCode}`] = false; // isPopoverVisible[`${hostId}-${paramCode}`] = false;
} }
function openHTML(id) { function openHTML(id) {
givePyAnchorId(id) console.log(id);
givePyAnchorId(id);
// upholdinfo({ // upholdinfo({
// "hostId": id, // "hostId": id,
@@ -466,7 +663,6 @@ function openHTML(id) {
// getlist(); // getlist();
// }) // })
} }
// function openAccountName(idStr) { // function openAccountName(idStr) {
@@ -496,7 +692,7 @@ function openHTML(id) {
.hostTable { .hostTable {
width: 100%; width: 100%;
padding: 40px 0; padding: 30px 0;
.hostIdText { .hostIdText {
text-decoration: underline; text-decoration: underline;
@@ -518,12 +714,10 @@ function openHTML(id) {
background: @btn-bg-color; background: @btn-bg-color;
border-radius: 10px; border-radius: 10px;
border: none; border: none;
} }
} }
.el-dialog { .el-dialog {
--el-dialog-font-line-height: 50px; --el-dialog-font-line-height: 50px;
--el-dialog-width: 600px; --el-dialog-width: 600px;
--el-dialog-border-radius: 8px; --el-dialog-border-radius: 8px;
@@ -547,7 +741,6 @@ function openHTML(id) {
.center-align { .center-align {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.center-flex { .center-flex {
@@ -559,13 +752,13 @@ function openHTML(id) {
<style scoped lang="less"> <style scoped lang="less">
::v-deep(.el-input__wrapper) { ::v-deep(.el-input__wrapper) {
background-color: #F2FAF9; background-color: #f2faf9;
border: 1px solid @bg-color; border: 1px solid @bg-color;
height: 44px; height: 44px;
} }
::v-deep(.el-select__wrapper) { ::v-deep(.el-select__wrapper) {
background-color: #F2FAF9; background-color: #f2faf9;
border: 1px solid @bg-color; border: 1px solid @bg-color;
height: 48px; height: 48px;
} }

View File

@@ -1,14 +1,14 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<Sidebar class="noneText" @activeIndex="activeIndexFn" /> <!-- <Sidebar class="noneText" @activeIndex="activeIndexFn" /> -->
<div class="content "> <div class="content ">
<div v-show="activeIndexA == 1"> <!-- <div v-show="activeIndexA == 1">
<workbenches /> <workbenches />
</div> </div> -->
<div v-show="activeIndexA == 2"> <div>
<hostsList /> <hostsList />
</div> </div>
<div style="position: absolute; bottom: 0; right: 0;">{{ version }}</div> <!-- <div style="position: absolute; bottom: 0; right: 0;">{{ version }}</div> -->
</div> </div>
@@ -16,10 +16,10 @@
</template> </template>
<script setup> <script setup>
import Sidebar from '../components/Sidebar.vue'; // import Sidebar from '../components/Sidebar.vue';
import { RouterLink, RouterView } from 'vue-router' import { RouterLink, RouterView } from 'vue-router'
import hostsList from '@/views/hosts/hostsList.vue' import hostsList from '@/views/hosts/hostsList.vue'
import workbenches from '@/views/hosts/workbenches.vue' // import workbenches from '@/views/hosts/workbenches.vue'
import { ref } from 'vue' import { ref } from 'vue'
import { getUser } from '@/utils/storage' import { getUser } from '@/utils/storage'
// import { usePythonBridge } from '@/utils/pythonBridge' // import { usePythonBridge } from '@/utils/pythonBridge'
@@ -29,12 +29,12 @@ import { getUser } from '@/utils/storage'
let activeIndexA = ref(1) // let activeIndexA = ref(1)
function activeIndexFn(data) { // function activeIndexFn(data) {
activeIndexA.value = data // activeIndexA.value = data
console.log(data) // console.log(data)
} // }
</script> </script>
@@ -73,8 +73,10 @@ html {
} }
.content { .content {
margin-left: 280px; // margin-left: 280px;
width: 1304px; margin-left: 25px;
margin-right: 25px;
width: 1540px;
height: 868px; height: 868px;
background: #FFFFFF; background: #FFFFFF;
border-radius: 36px; border-radius: 36px;