This commit is contained in:
pengxiaolong
2025-07-03 19:14:34 +08:00
parent 01e9c26821
commit 52415dee0b
10 changed files with 622 additions and 498 deletions

8
package-lock.json generated
View File

@@ -12,7 +12,7 @@
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"element-plus": "^2.9.7", "element-plus": "^2.9.7",
"pinia": "^3.0.1", "pinia": "^3.0.3",
"qwebchannel": "^6.2.0", "qwebchannel": "^6.2.0",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
@@ -9709,9 +9709,9 @@
} }
}, },
"node_modules/pinia": { "node_modules/pinia": {
"version": "3.0.1", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.1.tgz", "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz",
"integrity": "sha512-WXglsDzztOTH6IfcJ99ltYZin2mY8XZCXujkYWVIJlBjqsP6ST7zw+Aarh63E1cDVYeyUcPCxPHzJpEOmzB6Wg==", "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vue/devtools-api": "^7.7.2" "@vue/devtools-api": "^7.7.2"

View File

@@ -11,7 +11,7 @@
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"element-plus": "^2.9.7", "element-plus": "^2.9.7",
"pinia": "^3.0.1", "pinia": "^3.0.3",
"qwebchannel": "^6.2.0", "qwebchannel": "^6.2.0",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",

View File

@@ -1,5 +1,5 @@
import { getAxios, postAxios, downFile } from '@/utils/axios.js' import { getAxios, postAxios, downFile } from '@/utils/axios.js'
import { ElMessage } from 'element-plus';
//租户获取登录id //租户获取登录id
export function rentgetloginID(data) { export function rentgetloginID(data) {
return getAxios({ url: `/api/tenant/get-id-by-name?name=${data.name}`}) return getAxios({ url: `/api/tenant/get-id-by-name?name=${data.name}`})

View File

@@ -7,16 +7,13 @@ import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; // 引入中文语言包 import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; // 引入中文语言包
// createApp(App).use(store).use(router).mount('#app')
const app = createApp(App); const app = createApp(App);
app.use(ElementPlus, { app.use(ElementPlus, {
locale: zhCn, // 配置中文 locale: zhCn, // 配置中文
}); });
app.use(ElementPlus) // 注册 ElementPlus app.use(ElementPlus) // 注册 ElementPlus
app.use(createPinia()); // 注册 Pinia app.use(createPinia()); // 注册 Pinia
app.use(store); // 注册 store app.use(store); // 注册 store
app.use(router); // 注册 router app.use(router); // 注册 router
app.mount('#app'); app.mount('#app');

View File

@@ -9,4 +9,29 @@ export const noticeStore = defineStore('noticeNum', {
this.data.num++; this.data.num++;
}, },
}, },
}); });
export const tokenStore = defineStore('token', {
state: () => {
return { token: '' }
},
// 也可以这样定义
// state: () => ({ count: 0 })
actions: {
setToken(token){
this.token = token
}
},
})
export const UserStore = defineStore('User', {
state: () => {
return { user: {} }
},
// 也可以这样定义
// state: () => ({ count: 0 })
actions: {
setUser(user){
this.user = user
}
},
})

View File

@@ -8,6 +8,12 @@ import router from '@/router'
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { usePythonBridge, } from '@/utils/pythonBridge' import { usePythonBridge, } from '@/utils/pythonBridge'
import { ref } from 'vue';
import { defineStore } from 'pinia'
import { tokenStore,UserStore } from '@/stores/notice'
const { stopScript } = usePythonBridge(); const { stopScript } = usePythonBridge();
@@ -17,31 +23,34 @@ 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://47.79.98.113:8101" // baseURL = "http://47.79.98.113:8101"
// baseURL = "http://192.168.0.103:8085/" // baseURL = "http://192.168.0.103:8085/"
baseURL = "http://192.168.1.174:8101"
} 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://47.79.98.113:8101"
baseURL = "http://192.168.1.174:8101"
// baseURL = "http://api.tkpage.vvtiktok.cn" // baseURL = "http://api.tkpage.vvtiktok.cn"
} }
// 请求拦截器 // 请求拦截器
axios.interceptors.request.use((config) => { axios.interceptors.request.use((config) => {
const tokenCache = tokenStore()
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 == 'bigbrother-doLogin' || config.url == 'get-id-by-name')) {
config.headers['vvtoken'] = getToken();
}
// 请求超时时间 - 毫秒 // 请求超时时间 - 毫秒
config.timeout = 60000 config.timeout = 60000
config.baseURL = baseURL config.baseURL = baseURL
// 自定义Content-type // 自定义Content-type
config.headers['Content-type'] = 'application/json' config.headers['Content-type'] = 'application/json'
if (!(config.url == 'bigbrother-doLogin' || config.url == 'get-id-by-name')) {
config.headers['vvtoken'] = tokenCache.token;
}
return config; return config;
}, (error) => { }, (error) => {
return Promise.reject(error) return Promise.reject(error)
@@ -136,9 +145,11 @@ export const downFile = async (urlstr, data) => {
} }
//请求前验证 //请求前验证
function cheekalive() { function cheekalive() {
const userCache = UserStore()
const tokenCache = tokenStore()
axios.post('api/account/cheekalive', { axios.post('api/account/cheekalive', {
userId: getUser().userId, userId: userCache.user.id,
currcode: getToken(), currcode: tokenCache.token,
}, },
{ {
headers: { headers: {

View File

@@ -38,6 +38,43 @@ export function usePythonBridge() {
// }); // });
// }; // };
//删除前端储存数据
const deleteStorageData = (data) => {
return new Promise((resolve, reject) => {
if (pyBridge.value) {
pyBridge.value.deleteAccountInfo(JSON.stringify(data),function (result) {
resolve(result);
});
}else{
console.log("pyBridge is null未连接上")
}
});
};
//获取前端储存数据
const getStorageData = (data) => {
return new Promise((resolve, reject) => {
if (pyBridge.value) {
pyBridge.value.readAccountInfo(JSON.stringify(data),function (result) {
resolve(result);
});
}else{
console.log("pyBridge is null未连接上")
}
});
};
//设置前端储存数据
const setStorageData = (data) => {
return new Promise((resolve, reject) => {
if (pyBridge.value) {
pyBridge.value.storageAccountInfo(JSON.stringify(data),function (result) {
resolve(result);
});
}else{
console.log("pyBridge is null未连接上")
}
});
};
// 查询获取大哥的数据 // 查询获取大哥的数据
const controlTask = (data) => { const controlTask = (data) => {
@@ -58,7 +95,6 @@ export function usePythonBridge() {
if (pyBridge.value) { if (pyBridge.value) {
pyBridge.value.getBrotherInfo(function (result) { pyBridge.value.getBrotherInfo(function (result) {
resolve(JSON.parse(result)); resolve(JSON.parse(result));
// ElMessage.success(result);
}); });
}else{ }else{
console.log("pyBridge is null未连接上") console.log("pyBridge is null未连接上")
@@ -92,7 +128,6 @@ export function usePythonBridge() {
const givePyAnchorId = (id) => { const givePyAnchorId = (id) => {
console.log("id",id); console.log("id",id);
if (pyBridge.value) { if (pyBridge.value) {
ElMessage.success(id);
pyBridge.value.givePyAnchorId(id, function (result) { pyBridge.value.givePyAnchorId(id, function (result) {
}); });
} }
@@ -155,6 +190,9 @@ export function usePythonBridge() {
controlTask, controlTask,
getBrotherInfo, getBrotherInfo,
getVersion, getVersion,
givePyAnchorId givePyAnchorId,
getStorageData,
setStorageData,
deleteStorageData,
}; };
} }

View File

@@ -1,54 +1,70 @@
export function setToken(token) {
localStorage.setItem('token', token); import { usePythonBridge} from "@/utils/pythonBridge";
const { getStorageData, setStorageData,deleteStorageData} = usePythonBridge();
import { ElMessage } from 'element-plus';
export async function setToken(token) {
const res = await setStorageData({key: 'token',data: token}).then(res => {
});
} }
export function getToken() { export async function getToken() {
return localStorage.getItem('token'); const res = await getStorageData({ key: 'token' });
return JSON.parse(res);
} }
export function removeToken() { export async function removeToken() {
localStorage.removeItem('token'); const res = deleteStorageData({key: 'token'});
} }
export function setUser(user) { export async function setUser(user) {
const res = await setStorageData({key: 'user',data: user}).then(res => {
localStorage.setItem('user', JSON.stringify(user)); });
} }
export function getUser() { export async function getUser() {
return JSON.parse(localStorage.getItem('user')); const res = await getStorageData({ key: 'user' });
return JSON.parse(res);
} }
export function setNumData(numData) { export async function setNumData(numData) {
localStorage.setItem('num', JSON.stringify(numData)); const res = await setStorageData({key: 'num',data: numData})
} }
export function getNumData() {
return JSON.parse(localStorage.getItem('num')); export async function getNumData() {
const res = await getStorageData({ key: 'num' });
return JSON.parse(res);
} }
// 导出一个函数,用于设置用户密码 // 导出一个函数,用于设置用户密码
export function setUserPass(userdata) { export async function setUserPass(userdata) {
localStorage.setItem('userPass', JSON.stringify(userdata)); const res = await setStorageData({key: 'userPass',data:userdata})
} }
// 导出一个函数,用于获取用户密码 // 导出一个函数,用于获取用户密码
export function getUserPass() { export async function getUserPass() {
return JSON.parse(localStorage.getItem('userPass')); const res = await getStorageData({ key: 'userPass' });
return JSON.parse(res);
} }
// 用于设置tk账户密码 // 用于设置tk账户密码
export function setTkUser(userdata) { export async function setTkUser(userdata) {
localStorage.setItem('tkuser', JSON.stringify(userdata)); const res = await setStorageData({key: 'tkuser',data: userdata})
} }
// 用于获取tk账户密码 // 用于获取tk账户密码
export function getTkUser() {
return JSON.parse(localStorage.getItem('tkuser')); export async function getTkUser() {
const res = await getStorageData({ key: 'tkuser' });
return JSON.parse(res);
} }
// 用于列表筛选条件 // 用于列表筛选条件
export function setSerch(data) { export async function setSerch(data) {
localStorage.setItem('Serch', JSON.stringify(data)); const res = await setStorageData({key: 'Serch',data: data})
} }
// 用于获取列表筛选条件 // 用于获取列表筛选条件
export function getSerch() { export async function getSerch() {
return JSON.parse(localStorage.getItem('Serch')); const res = await getStorageData({ key: 'Serch' });
} return JSON.parse(res);
}

View File

@@ -1,356 +1,351 @@
<template> <template>
<div class="main"> <div class="main">
<div class="container"> <div class="container">
<div class="right"> <div class="right">
<img src="../assets/logoBg.png" class="background-video" alt=""> <img src="../assets/logoBg.png" class="background-video" alt="" />
<!-- 设置 --> <!-- 设置 -->
<div class="center-align"> <div class="center-align">
<div></div> <div></div>
<div class="setup"> <div class="setup">
<div class="setup-item center-justify"> <div class="setup-item center-justify">
<div></div> <div></div>
<span> <span> 网络设置 </span>
网络设置 </div>
</span> <div class="setup-item center-justify">
</div> <div></div>
<div class="setup-item center-justify"> <span> 简体中文 </span>
<div></div> </div>
<span> </div>
简体中文 </div>
</span> <div class="center-line" style="margin-top: 40px">
</div> <!-- logo -->
</div> <div class="logo">
</div> <!-- <div class="center-justify" style="height: 80px; width: 300px;">
<div class="center-line" style="margin-top: 40px;">
<!-- logo -->
<div class="logo">
<!-- <div class="center-justify" style="height: 80px; width: 300px;">
<img style="height: 100%;" src="@/assets/logotext.png"> <img style="height: 100%;" src="@/assets/logotext.png">
</div> --> </div> -->
</div> </div>
<!-- From --> <!-- From -->
<div class="from"> <div class="from">
<div class="from-title center-justify"> <div class="from-title center-justify">
<div>账号登陆</div> <div>账号登陆</div>
</div> </div>
<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
<el-input style="height: 25px;" v-model="formData.tenantName" placeholder="租户名称" style="height: 25px"
clearable @keyup.enter="onSubmit" /> v-model="formData.tenantName"
</div> placeholder="租户名称"
<div class="from-input-item1"> clearable
<img src="@/assets/username.png" alt=""> @keyup.enter="onSubmit"
<el-input style="height: 25px;" v-model="formData.userId" placeholder="账号" clearable />
@keyup.enter="onSubmit" /> </div>
</div> <div class="from-input-item1">
<div class="from-input-item1"> <img src="@/assets/username.png" alt="" />
<img src="@/assets/password.png" alt=""> <el-input
<el-input style="height: 25px; " v-model="formData.password" type="password" style="height: 25px"
placeholder="密码" show-password @keyup.enter="onSubmit" /> v-model="formData.userId"
</div> placeholder="账号"
clearable
@keyup.enter="onSubmit"
/>
</div>
<div class="from-input-item1">
<img src="@/assets/password.png" alt="" />
<el-input
style="height: 25px"
v-model="formData.password"
type="password"
placeholder="密码"
show-password
@keyup.enter="onSubmit"
/>
</div>
<div class="from-input-item"> <div class="from-input-item">
<el-button class="loginButton" color="#8f7ee7" type="primary" <el-button
@click="onSubmit">登录</el-button> class="loginButton"
color="#8f7ee7"
</div> type="primary"
</el-form> @click="onSubmit"
</div> >登录</el-button
</div> >
</div> </div>
<div class="version center-justify ">版本号{{ version }}</div> </el-form>
</div>
</div> </div>
</div>
</div> <div class="version center-justify">版本号{{ version }}</div>
</div> </div>
</div>
</div>
</template> </template>
<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, rentgetloginID } 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";
import { ElMessage } from 'element-plus';
import { tokenStore,UserStore } from '@/stores/notice'
const tokenCache = tokenStore()
const userCache = UserStore()
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(() => {
getVersion().then((res) => {
version.value = res;
});
getpassword();
}, 500);
});
setTimeout(() => { async function getpassword(){
getVersion().then((res) => { const res = await getUserPass();
version.value = res; formData.value = {
}) tenantName: res == null ? "" : res.tenantName,
// 测试localStorage; userId: res == null ? "" : res.userId,
testLocalStorage(); password: res == null ? "" : res.password,
}, 500); };
}
})
const router = useRouter(); const router = useRouter();
const formData = ref({ const formData = ref({});
tenantName: getUserPass() == null ? '' : getUserPass().tenantName,
userId: getUserPass() == null ? '' : getUserPass().userId,
password: getUserPass() == null ? '' : getUserPass().password,
});
const onSubmit = () => { const onSubmit = () => {
const loading = ElLoading.service({ const loading = ElLoading.service({
lock: true, lock: true,
text: 'Loading', text: "Loading",
background: 'rgba(0, 0, 0, 0.7)', background: "rgba(0, 0, 0, 0.7)",
}); });
setUserPass(formData.value); setUserPass(formData.value);
rentgetloginID({ rentgetloginID({
name: formData.value.tenantName, name: formData.value.tenantName,
}).then((res) => { })
console.log(res); .then((res) => {
console.log(res);
login({ login({
username: formData.value.userId, username: formData.value.userId,
tenantId: res, tenantId: res,
password: formData.value.password, password: formData.value.password,
}).then((res) => { })
loading.close(); .then((res) => {
console.log(res) loading.close();
setToken(res.tokenValue); console.log(res);
setUser(res); setToken(res.tokenValue);
router.push('/nav'); tokenCache.setToken(res.tokenValue)
}).catch((err) => { userCache.setUser(res)
loading.close(); setUser(res);
}); router.push("/nav");
})
}).catch((err) => { .catch((err) => {
loading.close(); loading.close();
console.log(err) });
}); })
.catch((err) => {
loading.close();
console.log(err);
});
}; };
</script> </script>
<style lang="less"> <style lang="less">
.main { .main {
width: 1600px; width: 1600px;
height: 900px; height: 900px;
overflow: hidden; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
/* 页面无法选中 */ /* 页面无法选中 */
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
.container { .container {
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
width: 1600px; width: 1600px;
height: 900px; height: 900px;
.right { .right {
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
width: 1600px; width: 1600px;
height: 900px; height: 900px;
padding: 20px 40px 20px 50px; padding: 20px 40px 20px 50px;
border-left: 3px solid #23516e; border-left: 3px solid #23516e;
position: relative; position: relative;
/* 添加 position: relative */ /* 添加 position: relative */
overflow: hidden; overflow: hidden;
/* 防止内容溢出 */ /* 防止内容溢出 */
.version { .version {
color: #fff; color: #fff;
position: absolute; position: absolute;
font-size: 20px; font-size: 20px;
bottom: 20px; bottom: 20px;
left: calc(50% - 50px); left: calc(50% - 50px);
// box-sizing: border-box; // box-sizing: border-box;
// width: 1600px; // width: 1600px;
}
} .background-video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
/* 确保视频在内容之下 */
}
.setup {
display: flex;
color: #fff;
.background-video { .setup-item {
position: absolute; padding: 10px 6px;
top: 0; display: flex;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
/* 确保视频在内容之下 */
}
.setup { div {
display: flex; width: 20px;
color: #fff; height: 20px;
border-radius: 50%;
background-color: rgb(255, 255, 255);
margin-right: 5px;
}
}
}
.setup-item { .logo {
padding: 10px 6px; padding: 20px 0;
display: flex; height: 80px;
}
div { .from {
width: 20px; width: 420px;
height: 20px; // height: 320px;
border-radius: 50%; color: @bg-color;
background-color: rgb(255, 255, 255); background-color: #ffffff44;
margin-right: 5px; border-radius: 20px;
} border: 1px solid #fff;
} padding: 32px;
} box-sizing: border-box;
.logo { .from-title {
padding: 20px 0; font-family: Source Han Sans SC;
height: 80px; font-weight: 500;
} font-size: 24px;
color: @bg-color;
line-height: 37px;
.from { div {
width: 420px; font-size: 20px;
// height: 320px; font-weight: 600;
color: @bg-color; // border-bottom: 4px solid #1db97d;
background-color: #ffffff44; }
border-radius: 20px; }
border: 1px solid #fff;
padding: 32px;
box-sizing: border-box;
.from-title { .from-input {
font-family: Source Han Sans SC; width: 100%;
font-weight: 500; padding: 15px 0;
font-size: 24px;
color: @bg-color;
line-height: 37px;
.from-input-item {
display: flex;
padding: 8px 0;
div { .from-input-item-title {
font-size: 20px; color: @bg-color;
font-weight: 600; font-size: 18px;
// border-bottom: 4px solid #1db97d; font-weight: 500;
} width: 80px;
} height: 50px;
}
.from-input { .loginButton {
width: 100%; width: 359px;
padding: 15px 0; height: 50px;
background: #ffffff;
border-radius: 24px;
border: 1px solid #ffffff;
.from-input-item { font-family: Source Han Sans SC;
display: flex; font-weight: 500;
padding: 8px 0; font-size: 18px;
color: @bg-color;
line-height: 37px;
}
}
.from-input-item-title { .from-input-item1 {
color: @bg-color; display: flex;
font-size: 18px; width: 359px;
font-weight: 500; height: 50px;
width: 80px; background: @bg-color-light-light;
height: 50px; border-radius: 24px;
} border: 1px solid #ffffff;
padding: 12px 25px 13px 25px;
.loginButton { box-sizing: border-box;
width: 359px; margin-bottom: 16px;
height: 50px; }
background: #FFFFFF; }
border-radius: 24px; }
border: 1px solid #FFFFFF; }
}
font-family: Source Han Sans SC;
font-weight: 500;
font-size: 18px;
color: @bg-color;
line-height: 37px;
}
}
.from-input-item1 {
display: flex;
width: 359px;
height: 50px;
background: @bg-color-light-light;
border-radius: 24px;
border: 1px solid #FFFFFF;
padding: 12px 25px 13px 25px;
box-sizing: border-box;
margin-bottom: 16px;
}
}
}
}
}
} }
.center-line { .center-line {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.center-justify { .center-justify {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
} }
.center-align { .center-align {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.center-flex { .center-flex {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.el-input__wrapper { .el-input__wrapper {
--el-input-focus-border-color: rgba(255, 255, 0, 0); --el-input-focus-border-color: rgba(255, 255, 0, 0);
--el-menu-hover-bg-color: rgba(255, 255, 0, 0); --el-menu-hover-bg-color: rgba(255, 255, 0, 0);
} }
</style> </style>
<style scoped lang="less"> <style scoped lang="less">
::v-deep(.el-input__wrapper) { ::v-deep(.el-input__wrapper) {
background-color: rgba(255, 0, 0, 0); background-color: rgba(255, 0, 0, 0);
box-shadow: none; box-shadow: none;
} }
::v-deep(.el-input__inner) { ::v-deep(.el-input__inner) {
color: #fff; color: #fff;
} }
::v-deep(.el-input__inner::placeholder) { ::v-deep(.el-input__inner::placeholder) {
color: @bg-color; color: @bg-color;
} }
</style> </style>

View File

@@ -1,15 +1,14 @@
<template> <template>
<div class="hostList"> <div class="hostList">
<div> <div>
<!-- --> <!-- -->
<div style="display: flex"> <div style="display: flex">
<div></div> <div></div>
<el-input <el-input
v-model="queryFormData.coinMin" v-model="queryFormData.coinMin"
placeholder="最小金币" placeholder="最小金币"
size="large" size="large"
style="width: 160px;" style="width: 160px"
type="number" type="number"
/> />
@@ -37,13 +36,19 @@
type="number" type="number"
/> />
<div style="width: 250px; margin-left: 50px;height: 50px;line-height: 50px;">当前网络{{ countryData }}</div> <div style="width: 250px; margin-left: 50px; height: 50px; line-height: 50px">
<div style="width: 160px; margin-left: 50px;height: 50px;line-height: 50px;">总数{{ getBrotherInfodata.total }}</div> 当前网络{{ countryData }}
<div style="width: 160px; margin-left: 50px;height: 50px;line-height: 50px;">有效数{{ getBrotherInfodata.valid }}</div> </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 <el-button
class="serch-button" class="serch-button"
style="margin-left: 50px ;" style="margin-left: 50px"
type="primary" type="primary"
@click="Resetss" @click="Resetss"
>重置</el-button >重置</el-button
@@ -51,7 +56,7 @@
<el-button <el-button
class="serch-button" class="serch-button"
style="margin-left: 50px ; width: 150px" style="margin-left: 50px; width: 150px"
type="primary" type="primary"
@click="openTikTok" @click="openTikTok"
>打开 TikTok 登录</el-button >打开 TikTok 登录</el-button
@@ -76,13 +81,13 @@
<!-- `````````````````````````````````````````````````````````````````````````````````````````````````` --> <!-- `````````````````````````````````````````````````````````````````````````````````````````````````` -->
<div style="width: 100%; border-bottom: 1px solid #e9e9e9; margin-top: 30px"></div> <div style="width: 100%; border-bottom: 1px solid #e9e9e9; margin-top: 30px"></div>
<!-- ···································································································· --> <!-- ···································································································· -->
<div style="display: flex; margin-top: 30px;flex-wrap: wrap;"> <div style="display: flex; margin-top: 30px; flex-wrap: wrap">
<el-select <el-select
v-model="searchForm.region" v-model="searchForm.region"
filterable filterable
placeholder="选择国家" placeholder="选择国家"
size="large" size="large"
style="width: 160px;" style="width: 160px"
> >
<el-option <el-option
v-for="item in options" v-for="item in options"
@@ -96,13 +101,13 @@
v-model="searchForm.displayId" v-model="searchForm.displayId"
placeholder="大哥id" placeholder="大哥id"
size="large" size="large"
style="width: 160px; margin-left: 50px;" style="width: 160px; margin-left: 50px"
clearable clearable
/> />
<el-button <el-button
class="serch-button" class="serch-button"
style="margin-left: 50px;" style="margin-left: 50px"
type="primary" type="primary"
@click="serch" @click="serch"
>查询</el-button >查询</el-button
@@ -117,8 +122,13 @@
@click="exportList" @click="exportList"
>导出Excel数据</el-button >导出Excel数据</el-button
> >
<el-button @click="filterdialogVisible = true" style="width: 50px;" class="put-button" type="primary"><img <el-button
style="height: 30px;" src="@/assets/filter.png"></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 <!-- <el-button @click="filterdialogVisible = true" style="width: 50px;" class="put-button" type="primary"><img
style="height: 30px;" src="@/assets/filter.png"></el-button> --> style="height: 30px;" src="@/assets/filter.png"></el-button> -->
</div> </div>
@@ -151,7 +161,6 @@
> >
<template v-if="label.paramCode != 'createDt'" #default="scope"> </template> <template v-if="label.paramCode != 'createDt'" #default="scope"> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<!-- ······································································································································ --> <!-- ······································································································································ -->
@@ -171,86 +180,108 @@
<!-- ·······································································弹窗······································································· --> <!-- ·······································································弹窗······································································· -->
<el-dialog v-model="filterdialogVisible" width="800px" :before-close="handleClose"> <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 HH:mm:ss"
placeholder="选择查询时间"
size="large"
style="width: 600px; margin-top: 10px"
/>
</el-col>
</el-row>
<el-row
v-for="(field, index) in fields"
:key="index"
:gutter="20"
style="margin-bottom: 10px"
>
<el-col :span="4">
<div style="height: 100%" class="center-justify">
{{ field.label }}
</div>
</el-col>
<el-col :span="10">
<div><label>最小值</label></div>
<el-input
type="number"
:oninput="'if(value.length>9)value=value.slice(0,9)'"
v-model.number="searchForm[field.minModel]"
placeholder="请输入最小值"
/>
</el-col>
<el-col :span="10">
<div><label>最大值</label></div>
<el-input
type="number"
:oninput="'if(value.length>9)value=value.slice(0,9)'"
v-model.number="searchForm[field.maxModel]"
placeholder="请输入最大值"
/>
</el-col>
</el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="4"> <el-col :span="4">
<!-- <label>选择筛选条件</label> --> <!-- <label>选择筛选条件</label> -->
<div style="height: 100%; padding-top: 10px" class="center-justify"> <div style="height: 100%; padding-top: 10px" class="center-justify">排序</div>
时间 </el-col>
</div> <el-col :span="10">
<div><label>排序类型</label></div>
</el-col> <el-select
<el-col :span="10"> v-model="sortData.sortName"
<div><label>开始时间/结束时间</label></div> filterable
placeholder="请选择"
style="width: 240px"
>
<el-option
v-for="item in sortNameOptions"
:key="item.type"
:label="item.label"
:value="item.type"
/>
</el-select>
</el-col>
<el-col :span="10">
<div><label>升序/降序</label></div>
<el-date-picker <el-select
v-model="createTimes" v-model="sortData.sort"
type="datetimerange" filterable
value-format="YYYY-MM-DD" placeholder="请选择"
placeholder="选择查询时间" style="width: 240px"
size="large" >
style="width: 600px;margin-top: 10px" <el-option
/> v-for="item in [
</el-col> { label: '升序', value: 'asc' },
</el-row> { label: '降序', value: 'desc' },
]"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-col>
</el-row>
<el-row v-for="(field, index) in fields" :key="index" :gutter="20" style="margin-bottom: 10px"> <template #footer>
<el-col :span="4"> <span class="dialog-footer">
<div style="height: 100%;" class="center-justify"> <el-button type="primary" @click="reset"> 重置 </el-button>
{{ field.label }} <!-- <el-button @click="filterdialogVisible = false">取消</el-button> -->
</div> <el-button type="primary" @click="handelClick"> 确认 </el-button>
</el-col> </span>
<el-col :span="10"> </template>
<div><label>最小值</label></div> </el-dialog>
<el-input type="number" :oninput="'if(value.length>9)value=value.slice(0,9)'"
v-model.number="searchForm[field.minModel]" placeholder="请输入最小值" />
</el-col>
<el-col :span="10">
<div><label>最大值</label></div>
<el-input type="number" :oninput="'if(value.length>9)value=value.slice(0,9)'"
v-model.number="searchForm[field.maxModel]" placeholder="请输入最大值" />
</el-col>
</el-row>
<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-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-select>
</el-col>
<el-col :span="10">
<div><label>升序/降序</label></div>
<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"
:label="item.label" :value="item.value" />
</el-select>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="reset">
重置
</el-button>
<!-- <el-button @click="filterdialogVisible = false">取消</el-button> -->
<el-button type="primary" @click="handelClick">
确认
</el-button>
</span>
</template>
</el-dialog>
</div> </div>
</div> </div>
</template> </template>
@@ -268,46 +299,45 @@ import {
getCountryinfo, getCountryinfo,
accountName, accountName,
} from "@/api/account"; } from "@/api/account";
import { usePythonBridge} from "@/utils/pythonBridge"; import { usePythonBridge } from "@/utils/pythonBridge";
import { getUser, setSerch, getSerch } from "@/utils/storage"; import { getUser, setSerch, getSerch } from "@/utils/storage";
import { ref, reactive, onMounted } from "vue"; import { ref, reactive, onMounted } from "vue";
import EChartsComponent from "@/components/EChartsComponent.vue"; import EChartsComponent from "@/components/EChartsComponent.vue";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import { color } from "echarts"; import { color } from "echarts";
import { getCountryName } from '@/utils/countryUtil' import { getCountryName } from "@/utils/countryUtil";
//ip国家 //ip国家
let countryData = ref(''); let countryData = ref("");
//获取国家 //获取国家
const getIpInfo = async () => { const getIpInfo = async () => {
try { try {
const response = await fetch('https://ipapi.co/json/'); const response = await fetch("https://ipapi.co/json/");
if (!response.ok) { if (!response.ok) {
throw new Error('请求失败'); 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',
// })
// })
} }
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登录 //打开TikTok登录
function openTikTok() { function openTikTok() {
@@ -315,7 +345,7 @@ function openTikTok() {
} }
//重置 //重置
function Resetss() { function Resetss() {
queryFormData.value = {} queryFormData.value = {};
} }
//大哥climb //大哥climb
const queryFormData = ref({ const queryFormData = ref({
@@ -326,41 +356,47 @@ const queryFormData = ref({
isRunning: true, isRunning: true,
}); });
//时间 //时间
const timerId = ref(null) const timerId = ref(null);
const getBrotherInfodata = ref({ const getBrotherInfodata = ref({
total: 0, total: 0,
valid: 0, valid: 0,
}) });
function BigBrotherstop() { function BigBrotherstop() {
queryFormData.value.tenantId = userInfo.value.tenantId; queryFormData.value.tenantId = userInfo.value.tenantId;
queryFormData.value.region = countryData.value; queryFormData.value.region = countryData.value;
controlTask(JSON.stringify(queryFormData.value)).then(res => { controlTask(JSON.stringify(queryFormData.value)).then((res) => {
queryFormData.value.isRunning = true; queryFormData.value.isRunning = true;
clearInterval(timerId.value) clearInterval(timerId.value);
timerId.value = null timerId.value = null;
}) });
} }
function getBigBrother() { function getBigBrother() {
queryFormData.value.tenantId = userInfo.value.tenantId; queryFormData.value.tenantId = userInfo.value.tenantId;
queryFormData.value.region = countryData.value; queryFormData.value.region = countryData.value;
controlTask(JSON.stringify(queryFormData.value)).then(res => { controlTask(JSON.stringify(queryFormData.value)).then((res) => {
queryFormData.value.isRunning = false; queryFormData.value.isRunning = false;
timerId.value = setInterval(() => { timerId.value = setInterval(() => {
getBrotherInfo().then(res => { getBrotherInfo().then((res) => {
getBrotherInfodata.value = res; getBrotherInfodata.value = res;
}) });
}, 1000) }, 1000);
}) });
} }
const loading = ref(false); const loading = ref(false);
//py方法 //py方法
const { givePyAnchorId, exportToExcel, loginTikTok , controlTask , getBrotherInfo } = usePythonBridge(); const {
givePyAnchorId,
exportToExcel,
loginTikTok,
controlTask,
getBrotherInfo,
} = usePythonBridge();
let num = ref(0); let num = ref(0);
//账号信息 //账号信息
const userInfo = ref(getUser()); const userInfo = ref({});
//主播列表DOM //主播列表DOM
const multipleTableRef = ref(null); const multipleTableRef = ref(null);
let labelList = ref([ let labelList = ref([
@@ -430,18 +466,24 @@ let options = ref([]);
let version = ref("0.0.0"); let version = ref("0.0.0");
onMounted(() => { onMounted(() => {
getCountry(); //获取国家 setTimeout(() => {
// getSerchStorage();//获取搜索条件 getUserdata();
getlist();//获取主播列表 }, 500);
getIpInfo();
}); });
async function getUserdata() {
const User = await getUser();
userInfo.value = User;
getCountry(); //获取国家
getlist(); //获取主播列表
getIpInfo();
}
function serch() { function serch() {
page.value = 1; page.value = 1;
getlist(); getlist();
} }
function exportList() { function exportList() {
// if (searchForm.value.dataType == "InvitationType") { // if (searchForm.value.dataType == "InvitationType") {
// searchForm.value.dataEnd = searchForm.value.dataStart; // searchForm.value.dataEnd = searchForm.value.dataStart;
@@ -482,11 +524,11 @@ function handleSelectionChange(data) {
//时间格式化 //时间格式化
function formatDate(date) { function formatDate(date) {
const year = date.getFullYear(); const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0开始需要+1 const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从 0开始需要+1
const day = String(date.getDate()).padStart(2, '0'); const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
} }
@@ -501,8 +543,8 @@ const getlist = () => {
sortName: sortData.value.sortName, //排序类型 sortName: sortData.value.sortName, //排序类型
current: page.value, current: page.value,
pageSize: pageSize.value, pageSize: pageSize.value,
createTimeStart:createTimes.value[0], createTimeStart: createTimes.value[0],
createTimeEnd:createTimes.value[1], createTimeEnd: createTimes.value[1],
...searchForm.value, //筛选条件 ...searchForm.value, //筛选条件
}).then((res) => { }).then((res) => {
loading.value = false; loading.value = false;
@@ -512,15 +554,15 @@ const getlist = () => {
console.log(res.records); console.log(res.records);
total.value = Number(res.total); total.value = Number(res.total);
tableData.value = res.records.map((item) => ({ tableData.value = res.records.map((item) => ({
level: item.level,// 等级 level: item.level, // 等级
createTime:formatDate(new Date(item.createTime)),// 创建时间 createTime: formatDate(new Date(item.createTime)), // 创建时间
followerCount: item.followerCount,// 粉丝数 followerCount: item.followerCount, // 粉丝数
followingCount: item.followingCount,// 关注数 followingCount: item.followingCount, // 关注数
hostDisplayId: item.hostDisplayId,// 所在直播间主播id hostDisplayId: item.hostDisplayId, // 所在直播间主播id
hostcoins: item.hostcoins,// 打赏的金币 hostcoins: item.hostcoins, // 打赏的金币
region: item.region,// 地区 region: item.region, // 地区
totalGiftCoins: item.totalGiftCoins,// 打赏金币总和 totalGiftCoins: item.totalGiftCoins, // 打赏金币总和
userIdStr: item.userIdStr,// 用户id userIdStr: item.userIdStr, // 用户id
displayId: item.displayId, displayId: item.displayId,
})); }));
} }
@@ -530,9 +572,9 @@ function handelClick() {
filterdialogVisible.value = false; filterdialogVisible.value = false;
} }
function reset() { function reset() {
searchForm.value = {} searchForm.value = {};
sortData.value = { sortName: "createTime", sort: "desc" } sortData.value = { sortName: "createTime", sort: "desc" };
createTimes.value = [] createTimes.value = [];
} }
function handleClose(done) { function handleClose(done) {
console.log("关闭"); console.log("关闭");
@@ -577,7 +619,7 @@ function filterTag(value, row) {
function getCountry() { function getCountry() {
getCountryinfo({}) getCountryinfo({})
.then((res) => { .then((res) => {
console.log('````````国家`````````',res); console.log("````````国家`````````", res);
res.forEach((item) => { res.forEach((item) => {
if (item.countryGroupName) { if (item.countryGroupName) {
options.value.push({ options.value.push({
@@ -586,7 +628,7 @@ function getCountry() {
}); });
} }
}); });
console.log('````````国家2`````````', options.value); console.log("````````国家2`````````", options.value);
}) })
.catch((err) => { .catch((err) => {
console.log("getCountry", err); console.log("getCountry", err);
@@ -650,7 +692,7 @@ function closePopover(hostId, paramCode) {
function openHTML(id) { function openHTML(id) {
console.log(id); console.log(id);
givePyAnchorId(id); givePyAnchorId(id);
// upholdinfo({ // upholdinfo({