上传代码
121
package-lock.json
generated
@@ -23,12 +23,14 @@
|
||||
"@vue/cli-plugin-router": "~5.0.0",
|
||||
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"less": "^4.2.2",
|
||||
"less-loader": "^12.2.0",
|
||||
"postcss-preset-env": "^10.1.5",
|
||||
"postcss-px-to-viewport": "^1.1.1",
|
||||
"postcss-px-viewport": "^0.0.4",
|
||||
"postcss-viewport-units": "^0.1.6"
|
||||
"postcss-viewport-units": "^0.1.6",
|
||||
"url-loader": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@achrinza/node-ipc": {
|
||||
@@ -7018,6 +7020,61 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/file-loader": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
|
||||
"integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"schema-utils": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^4.0.0 || ^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-loader/node_modules/loader-utils": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-loader/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
@@ -13209,6 +13266,68 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-loader": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz",
|
||||
"integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"mime-types": "^2.1.27",
|
||||
"schema-utils": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"file-loader": "*",
|
||||
"webpack": "^4.0.0 || ^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"file-loader": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/url-loader/node_modules/loader-utils": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-loader/node_modules/schema-utils": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
"ajv-keywords": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
"@vue/cli-plugin-router": "~5.0.0",
|
||||
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"less": "^4.2.2",
|
||||
"less-loader": "^12.2.0",
|
||||
"postcss-preset-env": "^10.1.5",
|
||||
"postcss-px-to-viewport": "^1.1.1",
|
||||
"postcss-px-viewport": "^0.0.4",
|
||||
"postcss-viewport-units": "^0.1.6"
|
||||
"postcss-viewport-units": "^0.1.6",
|
||||
"url-loader": "^4.1.1"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
||||
@@ -1,39 +1,67 @@
|
||||
import { getAxios, postAxios, downFile } from '@/utils/axios.js'
|
||||
|
||||
|
||||
|
||||
export function getIdByName(name) {
|
||||
return getAxios({ url: `/api/tenant/get-id-by-name?name=${name}` })
|
||||
}
|
||||
|
||||
//登录
|
||||
export function login(data) {
|
||||
return postAxios({ url: '/api/user/doLogin', data })
|
||||
}
|
||||
//获取国家
|
||||
export function getCountryinfo(data) {
|
||||
return postAxios({ url: '/api/common/country_info', data })
|
||||
return postAxios({ url: 'api/user/doLogin', data })
|
||||
}
|
||||
|
||||
//查询tk账号查询次数
|
||||
export function tkaccountuseinfo(accountName) {
|
||||
return getAxios({ url: `/api/common/accountCount?accountName=${accountName}` })
|
||||
//ai
|
||||
//获取所有话术列表
|
||||
export function getDialogList(data) {
|
||||
return postAxios({ url: 'ai/templateList', data })
|
||||
}
|
||||
//获取所有语言列表
|
||||
export function getLanguageList(data) {
|
||||
return postAxios({ url: 'ai/languageList', data })
|
||||
}
|
||||
//添加话术
|
||||
export function addDialog(data) {
|
||||
return postAxios({ url: 'ai/addTemplate', data })
|
||||
}
|
||||
//编辑话术
|
||||
export function editDialog(data) {
|
||||
return postAxios({ url: 'ai/editTemplate', data })
|
||||
}
|
||||
//删除话术
|
||||
export function deleteDialog(data) {
|
||||
return postAxios({ url: 'ai/deleteTemplate', data })
|
||||
}
|
||||
//删除语言
|
||||
export function deleteLanguage(data) {
|
||||
return postAxios({ url: 'ai/deleteLanguage', data })
|
||||
}
|
||||
//编辑语言
|
||||
export function editLanguage(data) {
|
||||
return postAxios({ url: 'ai/updateLanguage', data })
|
||||
}
|
||||
//添加语言
|
||||
export function addLanguage(data) {
|
||||
return postAxios({ url: 'ai/addLanguage', data })
|
||||
}
|
||||
|
||||
export function tkhostdata(data) {
|
||||
return postAxios({ url: '/api/save_data/hosts_info', data })
|
||||
|
||||
//小程序
|
||||
//获取配置列表
|
||||
export function getWxConfigList(data) {
|
||||
return postAxios({ url: 'pk/configList', data })
|
||||
}
|
||||
//添加配置
|
||||
export function addWxConfig(data) {
|
||||
return postAxios({ url: 'pk/addNewConfig', data })
|
||||
}
|
||||
//编辑配置
|
||||
export function editWxConfig(data) {
|
||||
return postAxios({ url: 'pk/updateConfig', data })
|
||||
}
|
||||
//删除配置
|
||||
export function deleteWxConfig(data) {
|
||||
return postAxios({ url: 'pk/deleteConfig', data })
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export function apiGetCart() {
|
||||
return getAxios({ url: '/cgi-bin/cart/latest' })
|
||||
}
|
||||
// export function login(data) {
|
||||
// return postAxios({ url: 'api/account/login', data })
|
||||
// }
|
||||
export function cheekalive(data) {
|
||||
return postAxios({ url: 'api/account/cheekalive', data })
|
||||
}
|
||||
|
||||
BIN
src/assets/MiniProgram.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
src/assets/ai.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/assets/icon.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
BIN
src/assets/plus.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/plus2.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 993 B |
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="sidebar">
|
||||
<div class="logo">
|
||||
<!-- <img style="margin-right: 10px;" src="@/assets/logo.png"> -->
|
||||
<!-- <div class="logo">
|
||||
<img style="margin-right: 10px;" src="@/assets/logo.png">
|
||||
<img src="@/assets/logotext.png">
|
||||
</div>
|
||||
</div> -->
|
||||
<ul>
|
||||
<li @click="updateActiveIndex(1)">
|
||||
<div>
|
||||
<img v-show="activeIndex == 1" src="@/assets/navAction.png" autoplay loop muted class="background-img">
|
||||
<div style="display: flex;">
|
||||
<img v-show="activeIndex == 1" src="@/assets/workAction.png" style="margin-right: 10px;">
|
||||
<img v-show="activeIndex == 2" src="@/assets/workAction.png" style="margin-right: 10px;">
|
||||
<div :style="activeIndex == 1 ? 'color: #000' : 'color: #fff'" class="center-justify">工作台</div>
|
||||
<img v-show="activeIndex == 1" src="@/assets/ai.png" style="margin-right: 10px;width: 24px;height: 24px;">
|
||||
<img v-show="activeIndex == 2" src="@/assets/ai.png" style="margin-right: 10px;width: 24px;height: 24px;">
|
||||
<div :style="activeIndex == 1 ? 'color: #000' : 'color: #fff'" class="center-justify">Ai后台管理</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,9 +21,9 @@
|
||||
<img v-show="activeIndex == 2" src="@/assets/navAction.png" autoplay loop muted class="background-img">
|
||||
|
||||
<div style="display: flex;">
|
||||
<img v-show="activeIndex == 2" src="@/assets/listAction.png" style="margin-right: 10px;">
|
||||
<img v-show="activeIndex == 1" src="@/assets/listAction.png" style="margin-right: 10px;">
|
||||
<div :style="activeIndex == 2 ? 'color: #000' : 'color: #fff'" class="center-justify">主播列表</div>
|
||||
<img v-show="activeIndex == 2" src="@/assets/MiniProgram.png" style="margin-right: 10px;width: 30px;height: 30px;">
|
||||
<img v-show="activeIndex == 1" src="@/assets/MiniProgram.png" style="margin-right: 10px;width: 30px;height: 30px;">
|
||||
<div :style="activeIndex == 2 ? 'color: #000' : 'color: #fff'" class="center-justify">小程序后台管理</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,19 +11,35 @@ const routes = [
|
||||
{
|
||||
path: '/nav',
|
||||
name: 'nav',
|
||||
// redirect: '/nav/hostsList', // 默认跳转
|
||||
redirect: '/nav/Home', // 默认跳转
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/nav.vue'),
|
||||
children: [
|
||||
{
|
||||
path: 'hostsList',
|
||||
name: 'hostsList',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/hostsList.vue')
|
||||
path: 'Home',
|
||||
name: 'Home',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/Home.vue'),
|
||||
},
|
||||
{
|
||||
path: 'workBenches',
|
||||
name: 'workBenches',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/workbenches.vue')
|
||||
},]
|
||||
path: 'scriptManagement',
|
||||
name: 'scriptManagement',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/ai/scriptManagement.vue'),
|
||||
},
|
||||
{
|
||||
path: 'LanguageManagement',
|
||||
name: 'LanguageManagement',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/ai/LanguageManagement.vue'),
|
||||
},
|
||||
{
|
||||
path: 'miniAM',
|
||||
name: 'miniAM',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/mini/miniAM.vue'),
|
||||
},
|
||||
{
|
||||
path: 'miniIntegral',
|
||||
name: 'miniIntegral',
|
||||
component: () => import(/* webpackChunkName: "hostsList" */ '../views/hosts/mini/miniIntegral.vue'),
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
const router = createRouter({
|
||||
|
||||
@@ -17,13 +17,13 @@ let baseURL = ''
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// 生产环境
|
||||
// baseURL = "https://api.tkpage.yolozs.com"
|
||||
baseURL = "http://192.168.1.174:8101"
|
||||
baseURL = "http://49.235.115.212:12025/"
|
||||
// baseURL = "http://192.168.0.103:8085/"
|
||||
} else {
|
||||
// 测试环境
|
||||
// baseURL = "http://120.26.251.180:8085/"
|
||||
// 开发环境
|
||||
baseURL = "https://api.tkpage.yolozs.com"
|
||||
baseURL = "http://49.235.115.212:12025/"
|
||||
// baseURL = "http://api.tkpage.vvtiktok.cn"
|
||||
}
|
||||
|
||||
@@ -32,15 +32,15 @@ axios.interceptors.request.use((config) => {
|
||||
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();
|
||||
}
|
||||
// if (!(config.url == 'templateList' || config.url == 'languageList')) {
|
||||
// config.headers['vvtoken'] = getToken();
|
||||
// }
|
||||
|
||||
// 请求超时时间 - 毫秒
|
||||
config.timeout = 60000
|
||||
config.baseURL = baseURL
|
||||
// 自定义Content-type
|
||||
config.headers['Content-type'] = 'application/json'
|
||||
// config.headers['Content-type'] = 'application/json'
|
||||
return config;
|
||||
}, (error) => {
|
||||
return Promise.reject(error)
|
||||
@@ -48,8 +48,8 @@ axios.interceptors.request.use((config) => {
|
||||
|
||||
// 响应拦截器
|
||||
axios.interceptors.response.use((response) => {
|
||||
console.log("response", response.data)
|
||||
if (response.data.code == 0) {
|
||||
console.log("```````````````response```````````````````", response.data)
|
||||
if (response.data.code == '200') {
|
||||
console.log("response", response.data.data)
|
||||
return response.data.data
|
||||
} else {
|
||||
@@ -83,14 +83,12 @@ export function getAxios({ url, params }) {
|
||||
// axios的post请求
|
||||
export function postAxios({ url, data }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log("```````````````data```````````````", data);
|
||||
console.log("````````````````url````````````````", url);
|
||||
|
||||
axios.post(
|
||||
url,
|
||||
data,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
).then(res => {
|
||||
resolve(res)
|
||||
}).catch(err => {
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
<!-- logo -->
|
||||
<div class="logo">
|
||||
<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="margin-right: 20px;height: 100%;" src="@/assets/logo.png">
|
||||
<img style="height: 100%;" src="@/assets/logotext.png"> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
|
||||
<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
|
||||
@@ -63,7 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="version center-justify ">版本号:{{ version }}</div>
|
||||
<!-- <div class="version center-justify ">版本号:{{ version }}</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
@@ -80,22 +75,22 @@ import { ElLoading } from 'element-plus';
|
||||
import { usePythonBridge } from '@/utils/pythonBridge'
|
||||
|
||||
|
||||
const { getVersion } = usePythonBridge();
|
||||
let version = ref('0.0.0');
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
getVersion().then((res) => {
|
||||
version.value = res;
|
||||
})
|
||||
}, 500);
|
||||
// const { getVersion } = usePythonBridge();
|
||||
// let version = ref('0.0.0');
|
||||
// onMounted(() => {
|
||||
// setTimeout(() => {
|
||||
// getVersion().then((res) => {
|
||||
// version.value = res;
|
||||
// })
|
||||
// }, 500);
|
||||
|
||||
})
|
||||
// })
|
||||
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const formData = ref({
|
||||
tenantName: getUserPass() == null ? '' : getUserPass().tenantName,
|
||||
// tenantName: getUserPass() == null ? '' : getUserPass().tenantName,
|
||||
userId: getUserPass() == null ? '' : getUserPass().userId,
|
||||
password: getUserPass() == null ? '' : getUserPass().password,
|
||||
});
|
||||
@@ -112,7 +107,7 @@ const onSubmit = () => {
|
||||
getIdByName(formData.value.tenantName).then((tenantId) => {
|
||||
console.log(tenantId)
|
||||
login({
|
||||
tenantId: Number(tenantId),
|
||||
// tenantId: Number(tenantId),
|
||||
username: formData.value.userId,
|
||||
password: formData.value.password,
|
||||
}).then((res) => {
|
||||
|
||||
38
src/views/hosts/Home.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref, // 响应式基础
|
||||
watch, // 侦听器
|
||||
onMounted, // 组件挂载完成后执行
|
||||
onUpdated, // 组件更新后执行
|
||||
onUnmounted, // 组件销毁前执行
|
||||
} from "vue";
|
||||
const refname = ref('');
|
||||
watch(refname, async (newQuestion, oldQuestion) => {
|
||||
// 变化后执行
|
||||
});
|
||||
onMounted(() => {
|
||||
// 组件挂载完成后执行
|
||||
});
|
||||
onUpdated(() => {
|
||||
// 组件更新后执行
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 组件销毁前执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.home {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
279
src/views/hosts/ai/LanguageManagement.vue
Normal file
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div class="language-management">
|
||||
<div class="content">
|
||||
<div class="languagetitle">
|
||||
<div class="title">语言管理</div>
|
||||
|
||||
<div class="add" @click="dialogVisible = true">
|
||||
<img class="add-img" src="@/assets/plus2.png" alt="" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 语言列表 -->
|
||||
<div class="languagelist">
|
||||
<el-table
|
||||
:data="tableData"
|
||||
stripe
|
||||
style="width: 100%; margin-top: 10px"
|
||||
max-height="700"
|
||||
>
|
||||
<el-table-column prop="language" label="语言名称" />
|
||||
<el-table-column prop="" label="" />
|
||||
<el-table-column prop="" label="" />
|
||||
<el-table-column prop="" label="" />
|
||||
<el-table-column label="操作">
|
||||
|
||||
<template #default="scope">
|
||||
<el-button size="small" @click="handleEdit(scope.$index, scope.row)">
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="handleDelete(scope.$index, scope.row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 编辑弹窗 -->
|
||||
<el-drawer v-model="dialogVisible" :with-header="false" @close="dialogVisible = false, languageNamedeta = {}">
|
||||
<div class="dialog-content">
|
||||
<div class="dialog-title">语言{{languageNamedeta.id? '编辑' : '新增'}}</div>
|
||||
<el-input
|
||||
v-model="languageNamedeta.language"
|
||||
style="width: 100%; margin-top: 20px"
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
placeholder="请输入语言内容"
|
||||
/>
|
||||
<div class="dialog-btn">
|
||||
<div class="dialogSave" @click="languageSave">保存</div>
|
||||
<div class="dialogCancel" @click="dialogVisible = false">取消</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { getLanguageList,deleteLanguage,editLanguage,addLanguage} from "@/api/account";
|
||||
import {
|
||||
ref, // 响应式基础
|
||||
watch, // 侦听器
|
||||
onMounted, // 组件挂载完成后执行
|
||||
onUpdated, // 组件更新后执行
|
||||
onUnmounted, // 组件销毁前执行
|
||||
} from "vue";
|
||||
const refname = ref("");
|
||||
const tableData = ref([]);
|
||||
const dialogVisible = ref(false);
|
||||
let languageNamedeta = ref({});// 编辑添加弹窗数据
|
||||
// 编辑弹窗
|
||||
function handleEdit(index, row) {
|
||||
dialogVisible.value = true;
|
||||
languageNamedeta.value = row;
|
||||
}
|
||||
// 保存语言
|
||||
function languageSave() {
|
||||
if (languageNamedeta.value.language == null) {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "请输入语言内容",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (languageNamedeta.value.id) {
|
||||
// 修改语言
|
||||
editLanguage(languageNamedeta.value)
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "修改成功",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "修改失败",
|
||||
});
|
||||
});
|
||||
dialogVisible.value = false;
|
||||
}else{
|
||||
// 新增语言
|
||||
addLanguage(languageNamedeta.value)
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "添加成功",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "添加失败",
|
||||
});
|
||||
});
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
}
|
||||
// 删除语言
|
||||
function handleDelete(index, row) {
|
||||
ElMessageBox.confirm("您确认要删除这个语言吗?")
|
||||
.then(() => {
|
||||
deleteLanguage({ id: row.id })
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "删除成功",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "删除失败",
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
watch(refname, async (newQuestion, oldQuestion) => {
|
||||
// 变化后执行
|
||||
});
|
||||
onMounted(() => {
|
||||
// // 组件挂载完成后执行
|
||||
// // 获取语言列表
|
||||
// getLanguageList()
|
||||
// .then((res) => {
|
||||
// tableData.value = res.data;
|
||||
// }).catch(() => {
|
||||
// ElMessage({
|
||||
// type: "error",
|
||||
// message: "获取语言列表失败",
|
||||
// });
|
||||
// });
|
||||
});
|
||||
onUpdated(() => {
|
||||
// 组件更新后执行
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 组件销毁前执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.language-management {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.content {
|
||||
width: 95%;
|
||||
height: 95%;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.languagetitle {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
background-color: #e2e2e2;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #999999;
|
||||
margin-left: 40px;
|
||||
}
|
||||
.add {
|
||||
width: 150px;
|
||||
height: 50px;
|
||||
background-color: #cccccc;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.add:hover {
|
||||
background-color: #999999;
|
||||
}
|
||||
.add-img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.languagelist {
|
||||
width: 97%;
|
||||
height: 85%;
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 10px;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.dialog-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.dialog-title {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
font-size: 25px;
|
||||
color: #b4b4b4;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.dialog-btn {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.dialogSave {
|
||||
width: 45%;
|
||||
height: 50px;
|
||||
background-color: #d6d6d6;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
}
|
||||
.dialogSave:hover {
|
||||
background-color: #b4b4b4;
|
||||
}
|
||||
.dialogCancel {
|
||||
width: 45%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
color: #d6d6d6;
|
||||
border: 1px solid #d6d6d6;
|
||||
}
|
||||
.dialogCancel:hover {
|
||||
background-color: #e7e6e6;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
399
src/views/hosts/ai/scriptManagement.vue
Normal file
@@ -0,0 +1,399 @@
|
||||
<template>
|
||||
<div class="scriptManagement">
|
||||
<div class="wordslist">
|
||||
<!-- 话术列表 -->
|
||||
<div class="wordscontent" ref="containerRef">
|
||||
<div
|
||||
class="words"
|
||||
v-for="(item, index) in LanguageData"
|
||||
:key="index"
|
||||
:id="item.language"
|
||||
>
|
||||
<div class="wordsname">{{ item.language }}</div>
|
||||
<div class="wordscontents">
|
||||
<div
|
||||
class="wordscontentstext"
|
||||
v-for="(items, indexs) in item.content"
|
||||
:key="index"
|
||||
>
|
||||
<div>{{ indexs + 1 + ". " + items.content }}</div>
|
||||
<div class="wordscontentstextbtn">
|
||||
<div style="margin-right: 10px" @click="handleEditor(items.id)">编辑</div>
|
||||
<div @click="handleDelete(items.id)">删除</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="Languagelist">
|
||||
<div class="Languagecontent">
|
||||
<!-- 话术添加 -->
|
||||
<div class="addwords" @click="wordsAddStatus = true">
|
||||
<img class="addwordsimg" src="@/assets/plus.png" />
|
||||
</div>
|
||||
<!-- 语言选择 -->
|
||||
<el-anchor
|
||||
class="Languageanchor"
|
||||
:container="containerRef"
|
||||
direction="vertical"
|
||||
type="default"
|
||||
:offset="30"
|
||||
@click="handleClick"
|
||||
>
|
||||
<el-anchor-link
|
||||
class="anchorLink"
|
||||
v-for="(item, index) in getLanguageListData"
|
||||
:href="'#' + item.language"
|
||||
:title="item.language"
|
||||
:key="index"
|
||||
/>
|
||||
</el-anchor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 话术编辑 -->
|
||||
<el-drawer v-model="dialogVisible" :with-header="false">
|
||||
<div class="dialog-content">
|
||||
<div class="dialog-title">话术编辑</div>
|
||||
<el-input
|
||||
v-model="handletextareadeta.content"
|
||||
style="width: 100%; margin-top: 20px"
|
||||
:rows="25"
|
||||
type="textarea"
|
||||
placeholder="请输入话术内容"
|
||||
/>
|
||||
<div class="dialog-btn">
|
||||
<div class="dialogSave" @click="handleSave">保存</div>
|
||||
<div class="dialogCancel" @click="dialogVisible = false">取消</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
<!-- 话术添加 -->
|
||||
<el-drawer v-model="wordsAddStatus" :with-header="false">
|
||||
<div class="dialog-content">
|
||||
<div class="dialog-title">话术编辑</div>
|
||||
<el-select v-model="wordsAddData.language" placeholder="请选择语言"></el-select>
|
||||
<el-input
|
||||
v-model="wordsAddData.content"
|
||||
style="width: 100%; margin-top: 20px"
|
||||
:rows="25"
|
||||
type="textarea"
|
||||
placeholder="请输入话术内容"
|
||||
/>
|
||||
<div class="dialog-btn">
|
||||
<div class="dialogSave" @click="handleSaveWordsAdd">保存</div>
|
||||
<div class="dialogCancel" @click="wordsAddStatus = false">取消</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getDialogList, getLanguageList, editDialog, deleteDialog,addDialog} from "@/api/account";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import {
|
||||
ref, // 响应式基础
|
||||
watch, // 侦听器
|
||||
onMounted, // 组件挂载完成后执行
|
||||
onUpdated, // 组件更新后执行
|
||||
onUnmounted, // 组件销毁前执行
|
||||
} from "vue";
|
||||
const refname = ref("");
|
||||
const containerRef = ref(null);
|
||||
const getDialogListData = ref([]);
|
||||
const getLanguageListData = ref([]);
|
||||
const LanguageData = ref([]);
|
||||
const wordsAddStatus = ref(false);
|
||||
const wordsAddData = ref({
|
||||
language: "",
|
||||
content: "",
|
||||
});
|
||||
|
||||
const handleClick = (e) => {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
//数据处理
|
||||
function groupContentByLanguage(arr1, arr2) {
|
||||
return arr2.map((item) => {
|
||||
// 过滤出对应语言的内容
|
||||
const contents = arr1
|
||||
.filter(({ language }) => language === item.language)
|
||||
// 按 id 排序
|
||||
.sort((a, b) => a.id - b.id)
|
||||
// 转换为所需格式
|
||||
.map(({ id, content }) => ({ id, content }));
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
language: item.language,
|
||||
content: contents,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const handletextareadeta = ref({});
|
||||
//添加话术
|
||||
function handleSaveWordsAdd() {
|
||||
if (wordsAddData.value.language === "" || wordsAddData.value.content === "") {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "请填写完整信息",
|
||||
});
|
||||
return;
|
||||
}
|
||||
addDialog(wordsAddData.value)
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "添加成功",
|
||||
});
|
||||
wordsAddStatus.value = false;
|
||||
getDialogListData.value = getDialogList();
|
||||
LanguageData.value = groupContentByLanguage(
|
||||
getDialogListData.value,
|
||||
getLanguageListData.value
|
||||
);
|
||||
}).catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "添加失败",
|
||||
});
|
||||
});
|
||||
}
|
||||
// 编辑
|
||||
function handleEditor(id) {
|
||||
dialogVisible.value = true;
|
||||
handletextareadeta.value = getDialogListData.value.find((item) => item.id === id);
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleSave() {
|
||||
editDialog({
|
||||
id: handletextareadeta.value.id,
|
||||
content: handletextareadeta.value.content,
|
||||
})
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "保存成功",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "保存失败",
|
||||
});
|
||||
});
|
||||
dialogVisible.value = false;
|
||||
getDialogListData.value = getDialogList();
|
||||
}
|
||||
// 删除
|
||||
function handleDelete(id) {
|
||||
ElMessageBox.confirm("您确认要删除这条话术吗?")
|
||||
.then(() => {
|
||||
deleteDialog({ id })
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "删除成功",
|
||||
});
|
||||
getDialogListData.value = getDialogList();
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "删除失败",
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
watch(refname, async (newQuestion, oldQuestion) => {
|
||||
// 变化后执行
|
||||
});
|
||||
onMounted(() => {
|
||||
// getDialogListData.value = getDialogList();
|
||||
// console.log(getDialogListData.value);
|
||||
// getLanguageListData.value = getLanguageList();
|
||||
LanguageData.value = groupContentByLanguage(
|
||||
getDialogListData.value,
|
||||
getLanguageListData.value
|
||||
);
|
||||
});
|
||||
onUpdated(() => {
|
||||
// 组件更新后执行
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 组件销毁前执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scriptManagement {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
}
|
||||
.wordslist {
|
||||
width: 87%;
|
||||
height: 97%;
|
||||
padding: 1% 1%;
|
||||
/* background-color: #00ff40; */
|
||||
}
|
||||
.Languagelist {
|
||||
height: 97%;
|
||||
width: 10%;
|
||||
padding: 1% 1% 1% 0%;
|
||||
/* background-color: #8d0000; */
|
||||
}
|
||||
.wordscontent {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
background-color: rgb(243, 243, 243);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.Languagecontent {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
background-color: rgb(243, 243, 243);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
scrollbar-width: none; /* 隐藏滚动条 */
|
||||
}
|
||||
.addwords {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background-color: rgb(226, 226, 226);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.addwords:hover{
|
||||
background-color: rgb(214, 214, 214);
|
||||
}
|
||||
.addwordsimg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
.Language {
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
background-color: rgb(226, 226, 226);
|
||||
margin-top: 20px;
|
||||
}
|
||||
.words {
|
||||
width: 95%;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.Languageanchor {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background-color: rgb(243, 243, 243);
|
||||
}
|
||||
.anchorLink {
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
border-radius: 5px;
|
||||
margin-left: -0.875vw;
|
||||
}
|
||||
.wordsname {
|
||||
font-size: 18px;
|
||||
color: #c9c9c9;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.wordscontents {
|
||||
width: 95%;
|
||||
/* min-height: 200px; */
|
||||
/* background-color: #ffffff; */
|
||||
border-radius: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.wordscontentstext {
|
||||
font-size: 16px;
|
||||
color: #7a7a7a;
|
||||
line-height: 24px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.wordscontentstextbtn {
|
||||
display: flex;
|
||||
}
|
||||
.dialog-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.dialog-title {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
font-size: 25px;
|
||||
color: #b4b4b4;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.dialog-btn {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.dialogSave {
|
||||
width: 45%;
|
||||
height: 50px;
|
||||
background-color: #d6d6d6;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
}
|
||||
.dialogSave:hover {
|
||||
background-color: #b4b4b4;
|
||||
}
|
||||
.dialogCancel {
|
||||
width: 45%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
color: #d6d6d6;
|
||||
border: 1px solid #d6d6d6;
|
||||
}
|
||||
.dialogCancel:hover {
|
||||
background-color: #e7e6e6;
|
||||
color: #ffffff;
|
||||
}
|
||||
/* 样式定义 */
|
||||
</style>
|
||||
@@ -1,576 +0,0 @@
|
||||
<template>
|
||||
<div class="hostList">
|
||||
<div>
|
||||
<div style="display: flex;">
|
||||
<el-select v-model="searchForm.country" 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>
|
||||
|
||||
<div></div>
|
||||
<el-date-picker v-model="searchForm.createTime" type="date" value-format="YYYY-MM-DD" placeholder="选择查询时间"
|
||||
size="large" style="margin-left: 50px;width: 160px;" />
|
||||
|
||||
<el-input v-model="searchForm.hostsId" 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="put-button" :disabled="tableData.length == 0" type="primary"
|
||||
@click="exportList">导出Excel数据</el-button>
|
||||
<!-- <el-button class="put-button" type="primary" @click="dialogFormVisible = true">分配给指定员工</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">
|
||||
<el-table ref="multipleTableRef" :data="tableData" stripe v-loading="loading" height="500"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="35" />
|
||||
|
||||
<el-table-column fixed prop="hostId" label="主播id" width="160">
|
||||
<template #default="scope">
|
||||
<div class="hostIdText" @click="openHTML(scope.row.hostId)"> {{
|
||||
scope.row.hostId }}</div>
|
||||
</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>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
|
||||
</div>
|
||||
<!-- 分页 -->
|
||||
<div class="center-justify" style="margin-top: 30px;">
|
||||
<el-pagination v-model:current-page="page" v-model:page-size="pageSize" background
|
||||
layout="sizes, prev, pager, next" :total="total" :page-sizes="[10, 20, 50, 100]"
|
||||
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<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-col :span="4">
|
||||
<div style="height: 100%; padding-top: 10px" 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-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.sortType" 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.sortForm" 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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// import { getToken, setToken, removeToken } from '@/utils/storage'
|
||||
import { tkhostdata, dicts, tkhostdetail, downList, getStaffList, 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';
|
||||
|
||||
const loading = ref(false)
|
||||
//py方法
|
||||
const { givePyAnchorId, exportToExcel } = usePythonBridge();
|
||||
|
||||
let num = ref(0)
|
||||
//账号信息
|
||||
const userInfo = ref(getUser())
|
||||
//主播列表DOM
|
||||
const multipleTableRef = ref(null)
|
||||
|
||||
let labelList = ref([
|
||||
{ paramCode: 'country', paramCodeMeaning: '国家' },
|
||||
{ paramCode: 'createTime', paramCodeMeaning: '创建时间' },
|
||||
{ paramCode: 'hostsCoins', paramCodeMeaning: '主播金币' },
|
||||
{ paramCode: 'yesterdayCoins', paramCodeMeaning: '昨日金币' },
|
||||
{ paramCode: 'fans', paramCodeMeaning: '粉丝数' },
|
||||
{ paramCode: 'fllowernum', paramCodeMeaning: '关注数' },
|
||||
{ paramCode: 'onlineFans', paramCodeMeaning: '在线粉丝' },
|
||||
{ paramCode: 'hostsKind', paramCodeMeaning: '主播类型' },
|
||||
]);
|
||||
const tableData = ref([])
|
||||
//主播列表传参
|
||||
const searchForm = ref({})
|
||||
const fields = [
|
||||
{ label: '粉丝数', minModel: 'fansMin', maxModel: 'fansMax' },
|
||||
{ label: '在线人数', minModel: 'onlineFansMin', maxModel: 'onlineFansMax' },
|
||||
{ label: '金币数', minModel: 'hostsCoinsMin', maxModel: 'hostsCoinsMax' },
|
||||
{ label: '关注数', minModel: 'fllowernumMin', maxModel: 'fllowernumMax' },
|
||||
]
|
||||
//排序
|
||||
let sortData = ref({ sortForm: 'desc', sortType: "createTime" })
|
||||
|
||||
//排序类型
|
||||
let sortNameOptions = ref([
|
||||
{ label: '创建时间', type: 'createTime' },
|
||||
{ label: '主播金币', type: 'hostsCoins' },
|
||||
{ label: '粉丝数', type: 'fans' },
|
||||
{ label: '昨日金币', type: 'yesterdayCoins' },
|
||||
{ label: '在线粉丝', type: 'onlineFans' },
|
||||
{ label: '关注数', type: 'fllowernum' },
|
||||
|
||||
])
|
||||
//员工选择列表
|
||||
let staffOptions = ref([])
|
||||
//筛选条件选择列表
|
||||
|
||||
//选择的员工
|
||||
let staffValue = ref('')
|
||||
//选择的主播列表
|
||||
let selectHostList = ref([])
|
||||
//分配弹窗是否弹出
|
||||
let dialogFormVisible = ref(false)
|
||||
//分配情况弹窗是否弹出
|
||||
let hostNameVisible = ref(false)
|
||||
|
||||
//备注弹窗是否弹出
|
||||
let commentVisible = ref(false)
|
||||
//筛选弹窗是否弹出
|
||||
let filterdialogVisible = ref(false)
|
||||
//分配的员工
|
||||
let staffId = ref({})
|
||||
//备注信息
|
||||
let commentInfo = ref('')
|
||||
//备注信息主播
|
||||
let commentHost = ref('')
|
||||
//分页
|
||||
let pageSize = ref(10)
|
||||
let page = ref(1)
|
||||
let total = ref(0)
|
||||
//是否渲染
|
||||
const isPopoverVisible = reactive({})
|
||||
|
||||
|
||||
let options = ref([])
|
||||
|
||||
let version = ref('0.0.0');
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
|
||||
|
||||
getCountry(); //获取国家
|
||||
|
||||
// getSerchStorage();//获取搜索条件
|
||||
|
||||
getlist();//获取主播列表
|
||||
})
|
||||
|
||||
function serch() {
|
||||
page.value = 1
|
||||
getlist();
|
||||
}
|
||||
|
||||
function exportList() {
|
||||
if (searchForm.value.dataType == 'InvitationType') {
|
||||
searchForm.value.dataEnd = searchForm.value.dataStart
|
||||
}
|
||||
exportToExcel({})
|
||||
|
||||
|
||||
// //浏览器导出方法
|
||||
// downList('export/hostsinfo',
|
||||
// {
|
||||
// searchTime: searchForm.value.time,
|
||||
// region: searchForm.value.country,
|
||||
// pageSize: pageSize.value,
|
||||
// page: page.value,
|
||||
// userId: userInfo.value.userId,
|
||||
// }
|
||||
// );
|
||||
|
||||
}
|
||||
//分页每页条数
|
||||
function handleSizeChange(val) {
|
||||
console.log(`${val} items per page`)
|
||||
getlist();
|
||||
|
||||
}
|
||||
//分页页数
|
||||
function handleCurrentChange(val) {
|
||||
console.log(`current page: ${val}`)
|
||||
getlist();
|
||||
|
||||
}
|
||||
//选择行
|
||||
function handleSelectionChange(data) {
|
||||
console.log(data)
|
||||
selectHostList.value = []
|
||||
data.forEach(item => {
|
||||
selectHostList.value.push(item.hostId)
|
||||
})
|
||||
// multipleTableRef.value = data
|
||||
// console.log(multipleTableRef.value)
|
||||
|
||||
}
|
||||
//获取主播列表
|
||||
const getlist = () => {
|
||||
|
||||
|
||||
loading.value = true
|
||||
console.log(searchForm.value)
|
||||
tkhostdata({
|
||||
tenantId: Number(userInfo.value.tenantId),
|
||||
sort: sortData.value.sortForm,//正序倒序
|
||||
sortName: sortData.value.sortType,//排序类型
|
||||
"current": page.value,
|
||||
"pageSize": pageSize.value,
|
||||
...searchForm.value,//筛选条件
|
||||
}).then(res => {
|
||||
loading.value = false
|
||||
if (res) {
|
||||
console.log('主播列表', res)
|
||||
total.value = Number(res.total)
|
||||
tableData.value = res.records.map(item => ({
|
||||
hostId: item.hostsId, // 注意:原字段是 hostId,你的数据是 hostsId,需手动映射
|
||||
hostlevel: item.hostsLevel, // 原字段 hostlevel 对应你的数据 hostsLevel
|
||||
country: item.country,
|
||||
createTime: item.createTime,
|
||||
fans: item.fans,
|
||||
fllowernum: item.fllowernum,
|
||||
hostsCoins: item.hostsCoins,
|
||||
hostsKind: item.hostsKind,
|
||||
onlineFans: item.onlineFans,
|
||||
yesterdayCoins: item.yesterdayCoins,
|
||||
// 保留原有字段(如 belongBy、useable 等)
|
||||
belongBy: item.belongBy,
|
||||
useable: item.useable
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
function handelClick() {
|
||||
filterdialogVisible.value = false
|
||||
}
|
||||
function reset() {
|
||||
searchForm.value.fansMin = null
|
||||
searchForm.value.fansMax = null
|
||||
searchForm.value.onlineFansMin = null
|
||||
searchForm.value.onlineFansMax = null
|
||||
searchForm.value.hostsCoinsMin = null
|
||||
searchForm.value.hostsCoinsMax = null
|
||||
searchForm.value.fllowernumMin = null
|
||||
searchForm.value.fllowernumMax = null
|
||||
}
|
||||
function handleClose(done) {
|
||||
console.log('关闭')
|
||||
// searchForm.value = {
|
||||
// dataType: '',
|
||||
// dataStart: '',
|
||||
// dataEnd: '',
|
||||
// }
|
||||
done()
|
||||
}
|
||||
|
||||
|
||||
//修改主播维护状态
|
||||
// function handleSelectChange(event, data) {
|
||||
|
||||
// upholdinfo({
|
||||
// "hostId": data.hostId,
|
||||
// "userId": userInfo.value.userId,
|
||||
// "tenantId": userInfo.value.tenantId,
|
||||
// // "comment": "我已经尽力维护,但是失败了",
|
||||
// "useable": event.target.value
|
||||
// }).then(res => {
|
||||
// console.log(res)
|
||||
// })
|
||||
// }
|
||||
|
||||
//更改主播维护备注
|
||||
|
||||
// function uphostcomment() {
|
||||
// upholdinfo({
|
||||
// "hostId": commentHost.value,
|
||||
// "userId": userInfo.value.userId,
|
||||
// "tenantId": userInfo.value.tenantId,
|
||||
// "comment": commentInfo.value,
|
||||
// }).then(res => {
|
||||
// console.log(res)
|
||||
// serch()
|
||||
// commentVisible.value = false
|
||||
// })
|
||||
// }
|
||||
|
||||
function filterTag(value, row) {
|
||||
console.log(row.useable, value)
|
||||
return row.useable === value;
|
||||
}
|
||||
|
||||
|
||||
//获取国家
|
||||
function getCountry() {
|
||||
getCountryinfo({}).then(res => {
|
||||
console.log(res)
|
||||
res.forEach(item => {
|
||||
if (item.countryGroupName) {
|
||||
options.value.push({ value: item.countryGroupName, label: item.countryGroupName })
|
||||
|
||||
}
|
||||
})
|
||||
console.log(options.value)
|
||||
}).catch(err => {
|
||||
console.log('getCountry', err)
|
||||
})
|
||||
}
|
||||
|
||||
//获取下级员工
|
||||
// const getStaff = () => {
|
||||
// getStaffList({
|
||||
// userId: userInfo.value.userId,
|
||||
// activeYn: userInfo.value.activeYn,
|
||||
// tenantId: userInfo.value.tenantId,
|
||||
// }).then(res => {
|
||||
// console.log(res)
|
||||
// res.forEach(item => {
|
||||
// staffOptions.value.push({
|
||||
// value: item.userId,
|
||||
// label: item.userName
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
// //分配主播给员工
|
||||
// function allocation() {
|
||||
// managerhosts({
|
||||
// "manaId": userInfo.value.userId,
|
||||
// "userId": staffValue.value,
|
||||
// "tenantId": userInfo.value.tenantId,
|
||||
// "hostIds": selectHostList.value
|
||||
// }).then(res => {
|
||||
// if (res) {
|
||||
// dialogFormVisible.value = false
|
||||
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
//获取主播信息
|
||||
// const getTkhostdetail = (id) => {
|
||||
// tkhostdetail({
|
||||
// hostId: id,
|
||||
// // page: 1,
|
||||
// searchTimeStart: '20250401',
|
||||
// searchTimeEnd: '20250403'
|
||||
// }).then(res => {
|
||||
|
||||
// console.log(labelList.value)
|
||||
|
||||
// })
|
||||
|
||||
// }
|
||||
|
||||
|
||||
function openPopover(hostId, paramCode) {
|
||||
|
||||
isPopoverVisible[`${hostId}-${paramCode}`] = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function closePopover(hostId, paramCode) {
|
||||
|
||||
// isPopoverVisible[`${hostId}-${paramCode}`] = false;
|
||||
}
|
||||
|
||||
|
||||
function openHTML(id) {
|
||||
givePyAnchorId(id)
|
||||
|
||||
// upholdinfo({
|
||||
// "hostId": id,
|
||||
// "userId": userInfo.value.userId,
|
||||
// "tenantId": userInfo.value.tenantId,
|
||||
// // "comment": "我已经尽力维护,但是失败了",
|
||||
// "useable": "Y"
|
||||
// }).then(res => {
|
||||
|
||||
// getlist();
|
||||
// })
|
||||
|
||||
}
|
||||
|
||||
// function openAccountName(idStr) {
|
||||
// if (idStr) {
|
||||
// hostNameVisible.value = true
|
||||
// accountName(idStr).then(res => {
|
||||
// staffId.value = JSON.stringify(res).replace(/[{}"]/g, '') // 移除所有 {} 和 "
|
||||
// .split(',') // 按逗号分割成数组
|
||||
|
||||
// console.log(res)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.hostList {
|
||||
box-sizing: border-box;
|
||||
// height: 100vh;
|
||||
padding: 40px;
|
||||
|
||||
/* 页面无法选中 */
|
||||
// -webkit-user-select: none;
|
||||
// -moz-user-select: none;
|
||||
// -ms-user-select: none;
|
||||
// user-select: none;
|
||||
|
||||
.hostTable {
|
||||
width: 100%;
|
||||
padding: 40px 0;
|
||||
|
||||
.hostIdText {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.serch-button {
|
||||
width: 80px;
|
||||
height: 47px;
|
||||
background: @btn-bg-color;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.put-button {
|
||||
width: 132px;
|
||||
height: 47px;
|
||||
background: @btn-bg-color;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.el-dialog {
|
||||
|
||||
--el-dialog-font-line-height: 50px;
|
||||
--el-dialog-width: 600px;
|
||||
--el-dialog-border-radius: 8px;
|
||||
|
||||
// border: 10px solid @bg-color-light;
|
||||
}
|
||||
|
||||
.center-line {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
// justify-content: center;
|
||||
}
|
||||
|
||||
.center-justify {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.center-align {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
.center-flex {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background-color: #F2FAF9;
|
||||
border: 1px solid @bg-color;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper) {
|
||||
background-color: #F2FAF9;
|
||||
border: 1px solid @bg-color;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
::v-deep(.el-pagination.is-background .el-pager li.is-active) {
|
||||
background-color: @bg-color;
|
||||
}
|
||||
</style>
|
||||
38
src/views/hosts/mini/miniAM.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="miniAM">
|
||||
小程序账号管理
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref, // 响应式基础
|
||||
watch, // 侦听器
|
||||
onMounted, // 组件挂载完成后执行
|
||||
onUpdated, // 组件更新后执行
|
||||
onUnmounted, // 组件销毁前执行
|
||||
} from "vue";
|
||||
const refname = ref('');
|
||||
watch(refname, async (newQuestion, oldQuestion) => {
|
||||
// 变化后执行
|
||||
});
|
||||
onMounted(() => {
|
||||
// 组件挂载完成后执行
|
||||
});
|
||||
onUpdated(() => {
|
||||
// 组件更新后执行
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 组件销毁前执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.miniAM {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
/* 样式定义 */
|
||||
</style>
|
||||
311
src/views/hosts/mini/miniIntegral.vue
Normal file
@@ -0,0 +1,311 @@
|
||||
<template>
|
||||
<div class="mini-integral">
|
||||
<div class="content">
|
||||
<!-- 积分配置列表 -->
|
||||
<div class="integral-list">
|
||||
<el-table
|
||||
:data="tableData"
|
||||
stripe
|
||||
style="width: 100%; margin-top: 10px"
|
||||
max-height="700"
|
||||
>
|
||||
<el-table-column prop="functionName" label="事件" />
|
||||
<el-table-column prop="" label="" />
|
||||
<el-table-column prop="functionValue" label="积分" />
|
||||
<el-table-column prop="" label="" />
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-button size="small" @click="miniIntegralEdit(scope.$index, scope.row)">
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
@click="miniIntegralDelete(scope.$index, scope.row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- 积分配置 -->
|
||||
<div class="integral-title">
|
||||
<div class="add" @click="dialogVisible = true">
|
||||
<img class="add-img" src="@/assets/plus2.png" alt="">
|
||||
</div>
|
||||
<div class="integral-text">
|
||||
<div class="h1">小</div>
|
||||
<div class="h1">程</div>
|
||||
<div class="h1">序</div>
|
||||
<div class="h1">积</div>
|
||||
<div class="h1">分</div>
|
||||
<div class="h1">配</div>
|
||||
<div class="h1">置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 新增修改积分配置弹窗 -->
|
||||
<el-drawer v-model="dialogVisible" :with-header="false" @close="dialogVisible = false, miniIntegraldeta = {}">
|
||||
<div class="dialog-content">
|
||||
<div class="dialog-title">事件{{miniIntegraldeta.id? '编辑' : '新增'}}</div>
|
||||
<el-input
|
||||
v-if="!miniIntegraldeta.id"
|
||||
v-model="miniIntegraldeta.functionName"
|
||||
style="width: 100%; margin-top: 20px"
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
placeholder="请输入事件名称"
|
||||
/>
|
||||
<el-input
|
||||
v-model="miniIntegraldeta.functionValue"
|
||||
style="width: 100%;height: 50px; margin-top: 20px"
|
||||
type="number"
|
||||
placeholder="请输入积分值"
|
||||
/>
|
||||
<div class="dialog-btn">
|
||||
<div class="dialogSave" @click="miniIntegralAddSave">保存</div>
|
||||
<div class="dialogCancel" @click="dialogVisible = false">取消</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import {
|
||||
getWxConfigList,
|
||||
addWxConfig,
|
||||
editWxConfig,
|
||||
deleteWxConfig,
|
||||
} from "@/api/account";
|
||||
import {
|
||||
ref, // 响应式基础
|
||||
watch, // 侦听器
|
||||
onMounted, // 组件挂载完成后执行
|
||||
onUpdated, // 组件更新后执行
|
||||
onUnmounted, // 组件销毁前执行
|
||||
} from "vue";
|
||||
const refname = ref("");
|
||||
const tableData = ref([
|
||||
{
|
||||
id: 1,
|
||||
functionName: "登录",
|
||||
functionValue: 10,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
functionName: "分享",
|
||||
functionValue: 20,
|
||||
},
|
||||
]);
|
||||
const dialogVisible = ref(false);
|
||||
const miniIntegraldeta = ref({});
|
||||
//保存积分配置
|
||||
function miniIntegralAddSave() {
|
||||
if (!miniIntegraldeta.value.functionName) {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "事件名称不能为空",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!miniIntegraldeta.value.functionValue) {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "积分值不能为空",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (miniIntegraldeta.value.id) {
|
||||
// 修改积分配置
|
||||
editWxConfig(miniIntegraldeta.value)
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "修改成功",
|
||||
});
|
||||
dialogVisible.value = false;
|
||||
miniIntegraldeta.value = {};
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "修改失败",
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 新增积分配置
|
||||
addWxConfig(miniIntegraldeta.value)
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "新增成功",
|
||||
});
|
||||
dialogVisible.value = false;
|
||||
miniIntegraldeta.value = {};
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "新增失败",
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
// 新增积分配置弹窗
|
||||
function miniIntegralEdit(index, row) {
|
||||
dialogVisible.value = true;
|
||||
miniIntegraldeta.value = row;
|
||||
console.log(index, row);
|
||||
}
|
||||
//删除积分配置
|
||||
function miniIntegralDelete(index, row) {
|
||||
ElMessageBox.confirm("您确认要删除这个积分配置吗?")
|
||||
.then(() => {
|
||||
deleteWxConfig({ id: row.id })
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "删除成功",
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "删除失败",
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
watch(refname, async (newQuestion, oldQuestion) => {
|
||||
// 变化后执行
|
||||
});
|
||||
onMounted(() => {
|
||||
// 组件挂载完成后执行
|
||||
});
|
||||
onUpdated(() => {
|
||||
// 组件更新后执行
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 组件销毁前执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mini-integral {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.content {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.3);
|
||||
padding: 40px;
|
||||
}
|
||||
.integral-list{
|
||||
width: 87%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.integral-title{
|
||||
width: 10%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.add{
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #c4c4c4;
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
.add:hover{
|
||||
background-color: #a9a9a9;
|
||||
}
|
||||
.add-img{
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.integral-text{
|
||||
width: 100%;
|
||||
height: 520px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
color: #c4c4c4;
|
||||
font-size: 25px;
|
||||
font-family: "SimSun", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
.h1{
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.dialog-title {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
font-size: 25px;
|
||||
color: #b4b4b4;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.dialog-btn {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.dialogSave {
|
||||
width: 45%;
|
||||
height: 50px;
|
||||
background-color: #d6d6d6;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
}
|
||||
.dialogSave:hover {
|
||||
background-color: #b4b4b4;
|
||||
}
|
||||
.dialogCancel {
|
||||
width: 45%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
color: #d6d6d6;
|
||||
border: 1px solid #d6d6d6;
|
||||
}
|
||||
.dialogCancel:hover {
|
||||
background-color: #e7e6e6;
|
||||
color: #ffffff;
|
||||
}
|
||||
/* 样式定义 */
|
||||
</style>
|
||||
@@ -1,741 +0,0 @@
|
||||
<template>
|
||||
<div class="center-line workbenches">
|
||||
<div class="center-align" style="width: 100%; margin: 0 20px;">
|
||||
<div class="box-card-num1 center-line">
|
||||
<div>总数量: <span>{{ hostData.totalCount }}</span></div>
|
||||
<div>新建主播: <span>{{ hostData.validAnchorsCount }}</span></div>
|
||||
<div> 已查询: <span>{{ hostData.checkedDataCount }}</span></div>
|
||||
<div>可邀请: <span>{{ hostData.canInvitationCount }}</span></div>
|
||||
<div>运行时间: <span>{{ formattedTime }}</span></div>
|
||||
|
||||
</div>
|
||||
<div class="center-line" style="padding-top: 15vh;">
|
||||
<el-button class="open-login" type="primary" @click="openTK">开启tk</el-button>
|
||||
<!-- <el-button class="open-login" type="primary" @click="startTimer">计时开始</el-button> -->
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<el-card class="box-card-num" v-for="(item, index) in 2" :key="index">
|
||||
<div class="center-justify">
|
||||
<div class="from-input-item">
|
||||
<div class="from-input-item-title center-justify">
|
||||
公会账号:
|
||||
</div>
|
||||
<el-input :disabled="!(tkData[index].code == 0 && !isLogin[index])"
|
||||
v-model="tkData[index].account" placeholder="请输入登录账号" clearable />
|
||||
</div>
|
||||
|
||||
<div class="from-input-item">
|
||||
<div class="from-input-item-title center-justify">
|
||||
公会密码:
|
||||
</div>
|
||||
<el-input :disabled="!(tkData[index].code == 0 && !isLogin[index])"
|
||||
v-model="tkData[index].password" type="password" placeholder="请输入登录密码" show-password />
|
||||
</div>
|
||||
|
||||
<el-button class="open-login" style="margin-left: 60px;"
|
||||
:disabled="!(tkData[index].code == 0 && !isLogin[index])" type="primary"
|
||||
@click="loginTK(index)">登录后台</el-button>
|
||||
<div v-if="tkData[index].code == 0" class="loginState"></div>
|
||||
<div v-if="tkData[index].code == 1" class="loginState" style="background-color: green;"></div>
|
||||
|
||||
</div>
|
||||
<div class="todayCount">今日已查询次数:{{ tkData[index].num }}</div>
|
||||
</el-card>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container ">
|
||||
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="center-justify"><img src="@/assets/worklogo.png">工作台 </span>
|
||||
<div style="margin-right: 120px;">当前网络:{{ countryData }}
|
||||
<!-- <el-button class="reset-button" @click="reset">重置数据</el-button> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<div class="input-group">
|
||||
<label>设置金币数量</label>
|
||||
<el-input type='number' v-model="pyData.gold.min" :min="0" :max="pyData.gold.max - 1"
|
||||
placeholder="最小值" style="width: 100%" :disabled="!pyData.isStart">
|
||||
<template #prepend>最小金币数</template>
|
||||
</el-input>
|
||||
<el-input type='number' v-model="pyData.gold.max" :min="pyData.gold.min + 1" :max="100"
|
||||
placeholder="最大值" style="width: 100%; margin-top: 10px" :disabled="!pyData.isStart">
|
||||
<template #prepend>最大金币数</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="input-group">
|
||||
<label>设置粉丝数量</label>
|
||||
<el-input type='number' v-model="pyData.fans.min" :min="0" :max="pyData.fans.max - 1"
|
||||
placeholder="最小值" style="width: 100%" :disabled="!pyData.isStart">
|
||||
<template #prepend>最小粉丝数</template>
|
||||
</el-input>
|
||||
<el-input type='number' v-model="pyData.fans.max" :min="pyData.fans.min + 1" :max="100"
|
||||
placeholder="最大值" style="width: 100%; margin-top: 10px" :disabled="!pyData.isStart">
|
||||
<template #prepend>最大粉丝数</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<div class="input-group">
|
||||
<label>后台查询频率</label>
|
||||
<!-- <el-input type='number' v-model="pyData.frequency.hour" @input="handleInputHour" -->
|
||||
<el-input type='number' v-model="pyData.frequency.hour" placeholder="次/小时"
|
||||
style="width: 100%" :disabled="!pyData.isStart">
|
||||
<template #append>次/小时</template>
|
||||
</el-input>
|
||||
<!-- <el-input type='number' v-model="pyData.frequency.day" @input="handleInputDay" -->
|
||||
<el-input type='number' v-model="pyData.frequency.day" placeholder="次/24小时"
|
||||
style="width: 100%; margin-top: 10px" :disabled="!pyData.isStart">
|
||||
<template #append>次/24小时</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div style="margin-top: 20px; text-align: center">
|
||||
|
||||
<el-button class="submit-button" :disabled="submitting" v-show="pyData.isStart" type="primary"
|
||||
@click="submit">开始获取数据</el-button>
|
||||
<el-button v-show="!pyData.isStart" type="danger" @click="unsubmit">停止获取</el-button>
|
||||
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { usePythonBridge, } from '@/utils/pythonBridge'
|
||||
import { setNumData, getNumData, getUser, setTkUser, getTkUser } from '@/utils/storage'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getCountryName } from '@/utils/countryUtil'
|
||||
import { tkaccountuseinfo } from '@/api/account'
|
||||
//导入python交互方法
|
||||
const { fetchDataConfig, fetchDataCount, loginBackStage, loginTikTok, backStageloginStatus, backStageloginStatusCopy } = usePythonBridge();
|
||||
|
||||
//ip国家
|
||||
let countryData = ref('');
|
||||
//获取主播数量的定时器
|
||||
let getHostTimer = ref(null);
|
||||
//获取的主播信息
|
||||
let hostData = ref({
|
||||
totalCount: 0,
|
||||
validAnchorsCount: 0,
|
||||
canInvitationCount: 0,
|
||||
checkedDataCount: 0,
|
||||
});
|
||||
//是否开启tk
|
||||
// let isTk = ref(true);
|
||||
|
||||
//账号是否登陆中
|
||||
let isLogin = ref([false, false]);
|
||||
//设置状态轮询定时器
|
||||
let statusTimer = ref(null);
|
||||
let statusTimerCopy = ref(null);
|
||||
|
||||
//设置次数最大值
|
||||
let maxCount = ref([
|
||||
{
|
||||
hourMax: 50,
|
||||
dayMax: 300,
|
||||
},
|
||||
{
|
||||
hourMax: 100,
|
||||
dayMax: 600,
|
||||
},
|
||||
]);
|
||||
|
||||
//tk账号信息
|
||||
let tkData = ref([
|
||||
{
|
||||
account: '',
|
||||
password: '',
|
||||
index: 1,
|
||||
code: 0,
|
||||
num: 0
|
||||
},
|
||||
{
|
||||
account: '',
|
||||
password: '',
|
||||
index: 2,
|
||||
code: 0,
|
||||
num: 0
|
||||
},
|
||||
]);
|
||||
|
||||
//python需要的数据
|
||||
let pyData = ref({
|
||||
gold: { min: 0, max: 0 },
|
||||
fans: { min: 0, max: 0 },
|
||||
frequency: { hour: 0, day: 0 },
|
||||
isStart: true,
|
||||
country: countryData.value,
|
||||
test: '123',
|
||||
test1: { test: 123, test12: 123 },
|
||||
tenantId: getUser().tenantId,
|
||||
userId: getUser().userId,
|
||||
});
|
||||
|
||||
//按钮提交状态
|
||||
let submitting = ref(true);
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
//从缓存获取数据
|
||||
if (getNumData()) {
|
||||
pyData.value = getNumData();
|
||||
}
|
||||
if (getTkUser()) {
|
||||
tkData.value = getTkUser();
|
||||
tkData.value[0].code = 0;
|
||||
tkData.value[1].code = 0;
|
||||
}
|
||||
|
||||
tkaccountuse(tkData.value[0].account, 0)
|
||||
tkaccountuse(tkData.value[1].account, 1)
|
||||
|
||||
getIpInfo()
|
||||
|
||||
|
||||
})
|
||||
|
||||
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',
|
||||
// })
|
||||
// })
|
||||
}
|
||||
};
|
||||
|
||||
//提交数据到py
|
||||
const submit = () => {
|
||||
pyData.value.country = countryData.value;
|
||||
console.log('提交的区间值:', pyData.value);
|
||||
// if (tkData.value[0].account == '' && tkData.value[1].account == '') {
|
||||
// ElMessage.error('请输入账号密码');
|
||||
// return;
|
||||
// }
|
||||
// if (tkData.value[0].password == '' && tkData.value[1].password == '') {
|
||||
// ElMessage.error('请输入账号密码');
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
if (((Number(pyData.value.gold.min) > Number(pyData.value.gold.max)) || (Number(pyData.value.fans.min) > Number(pyData.value.fans.max)))) {
|
||||
ElMessage.error('请输入正确的区间值');
|
||||
return;
|
||||
}
|
||||
if ((Number(pyData.value.gold.max) <= 0 || Number(pyData.value.fans.max <= 0)) || pyData.value.gold.max == '' || pyData.value.fans.max == '') {
|
||||
ElMessage.error('请输入正确的区间值');
|
||||
return;
|
||||
}
|
||||
if (Number(pyData.value.frequency.hour) <= 0 || Number(pyData.value.frequency.day) <= 0 || pyData.value.frequency.hour == '' || pyData.value.frequency.day == '') {
|
||||
ElMessage.error('请输入正确的频率区间值');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(
|
||||
'确认开始爬取数据?',
|
||||
'开始',
|
||||
{
|
||||
confirmButtonText: '开始',
|
||||
cancelButtonText: '取消',
|
||||
type: 'success',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
// console.log('提交的区间值:', pyData.value.gold, pyData.value.fans, pyData.value.frequency);
|
||||
//开始按钮的状态 改为禁用
|
||||
submitting.value = true;
|
||||
setNumData(pyData.value);
|
||||
console.error('提交的区间值:', JSON.stringify(pyData.value));
|
||||
|
||||
fetchDataConfig(JSON.stringify({
|
||||
gold: pyData.value.gold,
|
||||
fans: pyData.value.fans,
|
||||
frequency: pyData.value.frequency,
|
||||
isStart: true,
|
||||
country: countryData.value,
|
||||
tenantId: getUser().tenantId,
|
||||
userId: getUser().userId,
|
||||
})).then((res) => {
|
||||
//开始计时器
|
||||
startTimer();
|
||||
//开启查询次数
|
||||
getHostTimer.value = setInterval(() => {
|
||||
fetchDataCount().then((res) => {
|
||||
hostData.value = JSON.parse(res);
|
||||
tkaccountuse(tkData.value[0].account, 0)
|
||||
tkaccountuse(tkData.value[1].account, 1)
|
||||
})
|
||||
}, 5000);
|
||||
|
||||
|
||||
}).finally(() => {
|
||||
setTimeout(() => {
|
||||
pyData.value.isStart = false;
|
||||
submitting.value = false;
|
||||
}, 2000)
|
||||
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
//停止
|
||||
const unsubmit = () => {
|
||||
fetchDataConfig(JSON.stringify({
|
||||
gold: pyData.value.gold,
|
||||
fans: pyData.value.fans,
|
||||
frequency: pyData.value.frequency,
|
||||
isStart: false,
|
||||
country: countryData.value,
|
||||
tenantId: getUser().tenantId,
|
||||
userId: getUser().userId,
|
||||
})).then((res) => {
|
||||
pauseTimer();
|
||||
pyData.value.isStart = true;
|
||||
clearInterval(getHostTimer.value);
|
||||
getHostTimer.value = null;
|
||||
// ElMessage.sussec('已停止')
|
||||
}).catch((err) => {
|
||||
// ElMessage.error('停止失败')
|
||||
})
|
||||
};
|
||||
|
||||
//重置
|
||||
const reset = () => {
|
||||
pyData.value.gold = { min: 0, max: 0 };
|
||||
pyData.value.fans = { min: 0, max: 0 };
|
||||
pyData.value.frequency = { hour: 0, day: 0 };
|
||||
};
|
||||
|
||||
|
||||
const loginTK = (index) => {
|
||||
setTkUser(tkData.value)
|
||||
loginBackStage({
|
||||
account: tkData.value[index].account,
|
||||
password: tkData.value[index].password,
|
||||
index: index
|
||||
})
|
||||
if (index == 0) {
|
||||
isLogin.value[1] = true;
|
||||
statusTimer = setInterval(() => {
|
||||
getloginStatus();
|
||||
}, 2000)
|
||||
} else if (index == 1) {
|
||||
isLogin.value[0] = true;
|
||||
statusTimerCopy = setInterval(() => {
|
||||
getloginStatusCopy();
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const openTK = () => {
|
||||
// isTk.value = true;
|
||||
// console.log(isTk.value)
|
||||
loginTikTok();
|
||||
|
||||
}
|
||||
|
||||
function getloginStatus() {
|
||||
backStageloginStatus().then((res) => {
|
||||
const data = JSON.parse(res);
|
||||
tkData.value[data.index].code = data.code
|
||||
|
||||
if (data.code == 1) {
|
||||
clearInterval(statusTimer);
|
||||
statusTimer = null;
|
||||
submitting.value = false
|
||||
isLogin.value[1] = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
function getloginStatusCopy() {
|
||||
backStageloginStatusCopy().then((res) => {
|
||||
const data = JSON.parse(res);
|
||||
tkData.value[data.index].code = data.code
|
||||
|
||||
if (data.code == 1) {
|
||||
clearInterval(statusTimer);
|
||||
statusTimer = null;
|
||||
submitting.value = false
|
||||
isLogin.value[0] = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function tkaccountuse(id, index) {
|
||||
let num = 0;
|
||||
tkaccountuseinfo(id).then((res) => {
|
||||
if (res) {
|
||||
num = res
|
||||
tkData.value[index].num = num
|
||||
console.log('账号使用次数', tkData.value[index].num)
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log('账号使用次数', err)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const isRunning = ref(false);
|
||||
const totalSeconds = ref(0);
|
||||
//定时器
|
||||
let timerCrawl = null;
|
||||
|
||||
const startTimedata = ref(null);
|
||||
//清空时间 并开始运行
|
||||
const startTimer = () => {
|
||||
resetTimer();
|
||||
if (isRunning.value) return;
|
||||
isRunning.value = true;
|
||||
startTimedata.value = Date.now();
|
||||
timerCrawl = setInterval(() => {
|
||||
totalSeconds.value = Math.floor((Date.now() - startTimedata.value) / 1000);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
//结束运行 暂停
|
||||
const pauseTimer = () => {
|
||||
isRunning.value = false;
|
||||
clearInterval(timerCrawl);
|
||||
};
|
||||
//清空时间
|
||||
const resetTimer = () => {
|
||||
isRunning.value = false;
|
||||
clearInterval(timerCrawl);
|
||||
totalSeconds.value = 0;
|
||||
};
|
||||
// 格式化时间为 HH:MM:SS
|
||||
const formattedTime = computed(() => {
|
||||
const hours = Math.floor(totalSeconds.value / 3600);
|
||||
const minutes = Math.floor((totalSeconds.value % 3600) / 60);
|
||||
const seconds = totalSeconds.value % 60;
|
||||
|
||||
return [
|
||||
hours.toString().padStart(2, '0'),
|
||||
minutes.toString().padStart(2, '0'),
|
||||
seconds.toString().padStart(2, '0')
|
||||
].join(':');
|
||||
});
|
||||
|
||||
|
||||
function handleInputHour(value) {
|
||||
console.log(value)
|
||||
// 替换非数字字符为空字符串
|
||||
let num = value.replace(/[^\d]/g, '');
|
||||
// 如果值小于等于0,则设置为0
|
||||
if (Number(num) <= 0) {
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if ((tkData.value[0].code == 1) && (tkData.value[1].code == 1)) {
|
||||
if (Number(num) > maxCount.value[1].hourMax) {
|
||||
num = maxCount.value[1].hourMax;
|
||||
}
|
||||
} else if ((tkData.value[0].code == 1) || (tkData.value[1].code == 1)) {
|
||||
// 如果值大于最大值,则设置为最大值
|
||||
if (Number(num) > maxCount.value[0].hourMax) {
|
||||
num = maxCount.value[0].hourMax;
|
||||
}
|
||||
|
||||
} else {
|
||||
ElMessage.error('请先登录tk后台');
|
||||
num = 0;
|
||||
}
|
||||
// 更新模型
|
||||
pyData.value.frequency.hour = num;
|
||||
}
|
||||
|
||||
function handleInputDay(value) {
|
||||
console.log(value)
|
||||
// 替换非数字字符为空字符串
|
||||
let num = value.replace(/[^\d]/g, '');
|
||||
// 如果值小于等于0,则设置为0
|
||||
if (Number(num) <= 0) {
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if ((tkData.value[0].code == 1) && (tkData.value[1].code == 1)) {
|
||||
if (Number(num) > maxCount.value[1].dayMax) {
|
||||
num = maxCount.value[1].dayMax;
|
||||
}
|
||||
} else if ((tkData.value[0].code == 1) || (tkData.value[1].code == 1)) {
|
||||
// 如果值大于最大值,则设置为最大值
|
||||
if (Number(num) > maxCount.value[0].dayMax) {
|
||||
num = maxCount.value[0].dayMax;
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('请先登录tk后台');
|
||||
num = 0;
|
||||
}
|
||||
|
||||
|
||||
// 更新模型
|
||||
pyData.value.frequency.day = num;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.workbenches {
|
||||
padding: 45px 29px 22px 27px;
|
||||
|
||||
/* 页面无法选中 */
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.box-card {
|
||||
// width: 1240px;
|
||||
height: 436px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 21px 0px rgba(183, 183, 183, 0.33);
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.box-card-num1 {
|
||||
|
||||
width: 197px;
|
||||
height: 321px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 21px 0px rgba(183, 183, 183, 0.33);
|
||||
border-radius: 24px;
|
||||
// padding-top: 60px;
|
||||
box-sizing: border-box;
|
||||
|
||||
div {
|
||||
height: 20%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
|
||||
color: #8D8E8E;
|
||||
|
||||
span {
|
||||
color: #000;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.box-card-num {
|
||||
width: 897px;
|
||||
height: 145px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 21px 0px rgba(183, 183, 183, 0.33);
|
||||
border-radius: 24px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
padding-top: 18px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.todayCount {
|
||||
padding: 15px 21px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.from-input-item {
|
||||
display: flex;
|
||||
|
||||
.from-input-item-title {
|
||||
color: #000000;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.loginButton {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.loginState {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 50%;
|
||||
background-color: #b90000;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
font-family: Source Han Sans SC;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
color: #2D2727;
|
||||
line-height: 37px;
|
||||
|
||||
img {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.el-input {
|
||||
margin: 22px 0;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: bold;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.open-login {
|
||||
width: 100px;
|
||||
height: 47px;
|
||||
background: @btn-bg-color;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
width: 132px;
|
||||
height: 47px;
|
||||
background: @btn-bg-color;
|
||||
border-radius: 10px;
|
||||
|
||||
font-family: Source Han Sans SC;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
color: #FFFFFF;
|
||||
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 160px;
|
||||
height: 47px;
|
||||
background: @bg-color;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.center-line {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
// justify-content: center;
|
||||
}
|
||||
|
||||
.center-justify {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.center-align {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
.center-flex {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep(.el-input-group__prepend) {
|
||||
background: @bg-color-light;
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
border: 1px solid #B7CEC5;
|
||||
font-family: Source Han Sans SC;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
color: #FFFFFF;
|
||||
line-height: 37px;
|
||||
}
|
||||
|
||||
::v-deep(.el-input-group__append) {
|
||||
background: @bg-color-light;
|
||||
border-radius: 0px 10px 10px 0px;
|
||||
border: 1px solid #B7CEC5;
|
||||
font-family: Source Han Sans SC;
|
||||
font-weight: 400;
|
||||
font-size: 18px;
|
||||
color: #FFFFFF;
|
||||
line-height: 37px;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__wrapper) {
|
||||
width: 218px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 200px;
|
||||
height: 48px;
|
||||
background: #FFFFFF;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #B7CEC5;
|
||||
}
|
||||
</style>
|
||||
@@ -1,89 +1,205 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<Sidebar class="noneText" @activeIndex="activeIndexFn" />
|
||||
<div class="content ">
|
||||
<div v-show="activeIndexA == 1">
|
||||
<workbenches />
|
||||
</div>
|
||||
<div v-show="activeIndexA == 2">
|
||||
<hostsList />
|
||||
</div>
|
||||
<div style="position: absolute; bottom: 0; right: 0;">{{ version }}</div>
|
||||
<div class="common-layout">
|
||||
<el-container class="container">
|
||||
<el-aside :width="asideWidth" class="aside">
|
||||
<!-- logo -->
|
||||
<div class="logo" :style="{ width: isCollapse ? '4vw' : '10vw' }">
|
||||
<img
|
||||
class="logoimg"
|
||||
:style="{
|
||||
width: isCollapse ? '3vw' : '6vw',
|
||||
height: isCollapse ? '3vw' : '6vw',
|
||||
}"
|
||||
src="../assets//icon.png"
|
||||
alt="图标"
|
||||
/>
|
||||
</div>
|
||||
<!-- 收缩按钮 -->
|
||||
<div
|
||||
class="collapse-btn"
|
||||
:style="{ width: isCollapse ? '4vw' : '10vw' }"
|
||||
@click="toggleCollapse"
|
||||
>
|
||||
<el-icon v-if="isCollapse"><ArrowRightBold /></el-icon
|
||||
><el-icon v-else><ArrowLeftBold /></el-icon>
|
||||
</div>
|
||||
<!-- 菜单 -->
|
||||
<el-row class="row">
|
||||
<el-col :span="12">
|
||||
<el-menu
|
||||
default-active="/nav"
|
||||
background-color="#545c64"
|
||||
router
|
||||
text-color="#fff"
|
||||
@open="handleOpen"
|
||||
@close="handleClose"
|
||||
@select="handleSelect"
|
||||
:collapse="isCollapse"
|
||||
popper-offset="-115"
|
||||
class="menu"
|
||||
>
|
||||
<el-sub-menu index="1" class="sub-menu">
|
||||
<template #title>
|
||||
<el-icon><Tickets /></el-icon>
|
||||
<span>Ai管理</span>
|
||||
</template>
|
||||
<el-menu-item-group>
|
||||
<template #title><span>Ai</span></template>
|
||||
<el-menu-item index="/nav/scriptManagement">话术管理</el-menu-item>
|
||||
<el-menu-item index="/nav/LanguageManagement">语言管理</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
</el-sub-menu>
|
||||
|
||||
<el-sub-menu index="2" class="sub-menu">
|
||||
<template #title>
|
||||
<el-icon><Collection /></el-icon>
|
||||
<span>小程序管理</span>
|
||||
</template>
|
||||
<el-menu-item-group>
|
||||
<template #title><span>小程序</span></template>
|
||||
<el-menu-item index="/nav/miniAM">账号管理</el-menu-item>
|
||||
<el-menu-item index="/nav/miniIntegral">积分配置</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
</el-sub-menu>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-aside>
|
||||
|
||||
</div>
|
||||
<el-container>
|
||||
<!-- 顶部 -->
|
||||
<el-header class="header">
|
||||
<el-breadcrumb :separator-icon="ArrowRight">
|
||||
<el-breadcrumb-item :to="{ path: '/nav/Home' }">首页</el-breadcrumb-item>
|
||||
<el-breadcrumb-item
|
||||
v-for="(item, index) in breadcrumbList"
|
||||
:key="index"
|
||||
replace="true"
|
||||
:to="{ path: handleurl(item.path) }"
|
||||
>
|
||||
{{ item.name }}
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</el-header>
|
||||
<!-- 内容 -->
|
||||
<el-main class="main">
|
||||
<router-view>
|
||||
</router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Sidebar from '../components/Sidebar.vue';
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
import hostsList from '@/views/hosts/hostsList.vue'
|
||||
import workbenches from '@/views/hosts/workbenches.vue'
|
||||
import { ref } from 'vue'
|
||||
import { getUser } from '@/utils/storage'
|
||||
// import { usePythonBridge } from '@/utils/pythonBridge'
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
Menu as IconMenu,
|
||||
Message,
|
||||
Setting,
|
||||
Tickets,
|
||||
Collection,
|
||||
ArrowRightBold,
|
||||
ArrowLeftBold,
|
||||
} from "@element-plus/icons-vue";
|
||||
import { ArrowRight } from "@element-plus/icons-vue";
|
||||
import { RouterLink, RouterView } from "vue-router";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
let activeIndexA = ref(1)
|
||||
|
||||
function activeIndexFn(data) {
|
||||
activeIndexA.value = data
|
||||
console.log(data)
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const isCollapse = ref(false);
|
||||
const asideWidth = ref("10vw");
|
||||
const breadcrumbList = ref([]);
|
||||
//路由映射
|
||||
function convertPathsToMenuItems(paths) {
|
||||
const pathMap = {
|
||||
1: "ai管理",
|
||||
2: "小程序管理",
|
||||
"/nav/scriptManagement": "话术管理",
|
||||
"/nav/miniAM": "小程序账号管理",
|
||||
"/nav/miniIntegral": "积分配置",
|
||||
"/nav/LanguageManagement": "语言管理",
|
||||
};
|
||||
return paths.map((path) => {
|
||||
const name = pathMap[path];
|
||||
if (!name) throw new Error(`未找到路径 ${path} 对应的名称`);
|
||||
return { name, path };
|
||||
});
|
||||
}
|
||||
//面包屑
|
||||
function handleSelect(index, indexPath) {
|
||||
console.log("select", convertPathsToMenuItems(indexPath));
|
||||
breadcrumbList.value = convertPathsToMenuItems(indexPath);
|
||||
}
|
||||
//面包屑地址判断
|
||||
function handleurl(indexPath) {
|
||||
if (indexPath === "1" || indexPath === "2") {
|
||||
return "";
|
||||
} else {
|
||||
return indexPath;
|
||||
}
|
||||
}
|
||||
//菜单展开
|
||||
function toggleCollapse() {
|
||||
asideWidth.value = isCollapse.value ? "10vw" : "4vw";
|
||||
isCollapse.value = isCollapse.value ? false : true;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
<style scoped>
|
||||
.common-layout {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.app-container {
|
||||
.aside {
|
||||
height: 100vh;
|
||||
background-color: rgb(87, 87, 87);
|
||||
transition: width 0.3s ease; /* 添加过渡效果 */
|
||||
}
|
||||
.header {
|
||||
width: 85vw;
|
||||
height: 4vh;
|
||||
background-color: rgb(255, 255, 255);
|
||||
display: flex;
|
||||
width: 1600px;
|
||||
height: 900px;
|
||||
background-color: @bg-color;
|
||||
position: relative;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.noneText {
|
||||
/* 页面无法选中 */
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
background-color: @bg-color;
|
||||
padding: 20px;
|
||||
/* box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1); */
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 280px;
|
||||
width: 1304px;
|
||||
height: 868px;
|
||||
background: #FFFFFF;
|
||||
border-radius: 36px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.center-justify {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
.main {
|
||||
width: 100%;
|
||||
height: 90vh;
|
||||
background-color: rgb(199, 199, 199);
|
||||
}
|
||||
.logo {
|
||||
margin-top: 10px;
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
line-height: 10vh;
|
||||
width: 10vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.logoimg {
|
||||
transition: width 0.3s ease; /* 添加过渡效果 */
|
||||
transition: height 0.3s ease; /* 添加过渡效果 */
|
||||
border-radius: 20%;
|
||||
}
|
||||
.row {
|
||||
width: 10vw;
|
||||
height: 80vh;
|
||||
}
|
||||
.menu {
|
||||
width: 10vw;
|
||||
font-size: 30px;
|
||||
}
|
||||
.collapse-btn {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transition: width 0.3s ease; /* 添加过渡效果 */
|
||||
background-color: #3b4046;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -23,5 +23,6 @@ module.exports = defineConfig({
|
||||
additionalData: `@import "@/static/css/app.less";` // 注入全局变量文件
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||