备份
This commit is contained in:
@@ -72,4 +72,7 @@ export function upholdinfo(data) {
|
|||||||
export function accountName(str) {
|
export function accountName(str) {
|
||||||
return postAxios({ url: 'api/account/accountName?accounts=' + str })
|
return postAxios({ url: 'api/account/accountName?accounts=' + str })
|
||||||
}
|
}
|
||||||
|
//查看直播间信息
|
||||||
|
export function liveHostDetail(data) {
|
||||||
|
return postAxios({ url: 'api/save_data/live_host_detail', data })
|
||||||
|
}
|
||||||
|
|||||||
BIN
src/assets/wifi.png
Normal file
BIN
src/assets/wifi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
240
src/components/LiveRecordDialog.vue
Normal file
240
src/components/LiveRecordDialog.vue
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
<!-- LiveRecordDialog.vue -->
|
||||||
|
<template>
|
||||||
|
<el-dialog v-model="visible" title="直播记录" width="86vw" top="6vh" :close-on-click-modal="false" destroy-on-close>
|
||||||
|
<!-- 顶部工具栏 -->
|
||||||
|
<div class="toolbar">
|
||||||
|
<div class="left">
|
||||||
|
<el-input v-model="kw" placeholder="搜索:hostsId / userId / tenantId / id" clearable
|
||||||
|
style="width: 320px" />
|
||||||
|
<el-select v-model="sortKey" style="width: 170px" placeholder="排序字段">
|
||||||
|
<el-option label="开始时间" value="startTimeFormatted" />
|
||||||
|
<el-option label="结束时间" value="endTimeFormatted" />
|
||||||
|
<el-option label="点赞数" value="likeCount" />
|
||||||
|
<el-option label="粉丝团" value="fansClubCount" />
|
||||||
|
</el-select>
|
||||||
|
<el-select v-model="sortOrder" style="width: 140px" placeholder="排序方式">
|
||||||
|
<el-option label="降序" value="desc" />
|
||||||
|
<el-option label="升序" value="asc" />
|
||||||
|
</el-select>
|
||||||
|
|
||||||
|
<el-checkbox v-model="onlyAbnormal">只看异常</el-checkbox>
|
||||||
|
|
||||||
|
<el-button @click="reset">重置</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<el-tag type="info">总条数:{{ filteredRows.length }}</el-tag>
|
||||||
|
<el-tag type="success">点赞合计:{{ totalLikes }}</el-tag>
|
||||||
|
<el-tag type="warning">like=0:{{ zeroLikeCount }}</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table :data="pagedRows" border height="62vh" style="width: 100%"
|
||||||
|
:default-sort="{ prop: 'startTimeFormatted', order: 'descending' }">
|
||||||
|
<el-table-column prop="id" label="ID" width="90" />
|
||||||
|
<el-table-column prop="userId" label="userId" width="90" />
|
||||||
|
<el-table-column prop="hostsId" label="hostsId" width="130" />
|
||||||
|
<el-table-column prop="tenantId" label="tenantId" width="100" />
|
||||||
|
|
||||||
|
<el-table-column prop="fansClubCount" label="粉丝团" width="90" />
|
||||||
|
<el-table-column prop="lightedVsTotalGifts" label="点亮/礼物" width="110" />
|
||||||
|
|
||||||
|
<el-table-column prop="startTimeFormatted" label="开始时间" width="170" />
|
||||||
|
<el-table-column prop="endTimeFormatted" label="结束时间" width="170" />
|
||||||
|
<el-table-column prop="durationFormatted" label="时长" width="120" />
|
||||||
|
|
||||||
|
<el-table-column prop="likeCount" label="点赞" width="110" sortable>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.likeCount === 0" type="danger">0</el-tag>
|
||||||
|
<span v-else>{{ row.likeCount }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column prop="createTime" label="入库时间" width="170" />
|
||||||
|
|
||||||
|
<el-table-column label="操作" fixed="right" width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button size="small" @click="copyRow(row)">复制</el-button>
|
||||||
|
<el-button size="small" type="primary" @click="emitSelect(row)">选中</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<el-pagination v-model:current-page="page" v-model:page-size="pageSize" :page-sizes="[10, 20, 50, 100]"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper" :total="filteredRows.length" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="visible = false">关闭</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from "vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
|
type Row = {
|
||||||
|
id: number;
|
||||||
|
userId: number;
|
||||||
|
hostsId: string;
|
||||||
|
tenantId: number;
|
||||||
|
fansClubCount: number;
|
||||||
|
lightedVsTotalGifts: string;
|
||||||
|
startTimeFormatted: string;
|
||||||
|
endTimeFormatted: string;
|
||||||
|
likeCount: number;
|
||||||
|
durationFormatted: string;
|
||||||
|
createTime: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: boolean;
|
||||||
|
rows: Row[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "update:modelValue", v: boolean): void;
|
||||||
|
(e: "select", row: Row): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (v) => emit("update:modelValue", v),
|
||||||
|
});
|
||||||
|
|
||||||
|
const kw = ref("");
|
||||||
|
const sortKey = ref<keyof Row>("startTimeFormatted");
|
||||||
|
const sortOrder = ref<"asc" | "desc">("desc");
|
||||||
|
const onlyAbnormal = ref(false);
|
||||||
|
|
||||||
|
const page = ref(1);
|
||||||
|
const pageSize = ref(20);
|
||||||
|
|
||||||
|
watch([kw, sortKey, sortOrder, onlyAbnormal], () => {
|
||||||
|
page.value = 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
function parseTime(s?: string) {
|
||||||
|
// "2025-12-18 13:12:11" -> Date
|
||||||
|
if (!s) return 0;
|
||||||
|
return new Date(s.replace(" ", "T")).getTime() || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function durationSeconds(durationFormatted?: string) {
|
||||||
|
// 例:"2小时49分钟55秒" / "18分钟31秒" / "25秒"
|
||||||
|
if (!durationFormatted) return 0;
|
||||||
|
const h = Number((durationFormatted.match(/(\d+)\s*小时/) || [])[1] || 0);
|
||||||
|
const m = Number((durationFormatted.match(/(\d+)\s*分钟/) || [])[1] || 0);
|
||||||
|
const s = Number((durationFormatted.match(/(\d+)\s*秒/) || [])[1] || 0);
|
||||||
|
return h * 3600 + m * 60 + s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredRows = computed(() => {
|
||||||
|
const k = kw.value.trim().toLowerCase();
|
||||||
|
|
||||||
|
let arr = (props.rows || []).filter((r) => {
|
||||||
|
if (!k) return true;
|
||||||
|
const hay = `${r.id} ${r.userId} ${r.hostsId} ${r.tenantId}`.toLowerCase();
|
||||||
|
return hay.includes(k);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (onlyAbnormal.value) {
|
||||||
|
arr = arr.filter((r) => r.likeCount === 0 || durationSeconds(r.durationFormatted) < 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
const key = sortKey.value;
|
||||||
|
const order = sortOrder.value;
|
||||||
|
|
||||||
|
arr = [...arr].sort((a, b) => {
|
||||||
|
const av = a[key] as any;
|
||||||
|
const bv = b[key] as any;
|
||||||
|
|
||||||
|
// 时间字段特殊处理
|
||||||
|
if (key === "startTimeFormatted" || key === "endTimeFormatted" || key === "createTime") {
|
||||||
|
const aa = parseTime(String(av));
|
||||||
|
const bb = parseTime(String(bv));
|
||||||
|
return order === "desc" ? bb - aa : aa - bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数字
|
||||||
|
if (typeof av === "number" && typeof bv === "number") {
|
||||||
|
return order === "desc" ? bv - av : av - bv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字符串
|
||||||
|
return order === "desc"
|
||||||
|
? String(bv).localeCompare(String(av))
|
||||||
|
: String(av).localeCompare(String(bv));
|
||||||
|
});
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
});
|
||||||
|
|
||||||
|
const pagedRows = computed(() => {
|
||||||
|
const start = (page.value - 1) * pageSize.value;
|
||||||
|
return filteredRows.value.slice(start, start + pageSize.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalLikes = computed(() =>
|
||||||
|
filteredRows.value.reduce((sum, r) => sum + (Number(r.likeCount) || 0), 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
const zeroLikeCount = computed(() => filteredRows.value.filter((r) => r.likeCount === 0).length);
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
kw.value = "";
|
||||||
|
sortKey.value = "startTimeFormatted";
|
||||||
|
sortOrder.value = "desc";
|
||||||
|
onlyAbnormal.value = false;
|
||||||
|
page.value = 1;
|
||||||
|
pageSize.value = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyRow(row: Row) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(JSON.stringify(row, null, 2));
|
||||||
|
ElMessage.success("已复制该行 JSON");
|
||||||
|
} catch {
|
||||||
|
ElMessage.warning("复制失败:浏览器不支持或无权限");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitSelect(row: Row) {
|
||||||
|
emit("select", row);
|
||||||
|
ElMessage.success(`已选中:ID ${row.id}`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.toolbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar .left {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar .right {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -17,7 +17,7 @@ let baseURL = ''
|
|||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
// 生产环境
|
// 生产环境
|
||||||
// baseURL = "https://api.tkpage.yolozs.com"
|
// baseURL = "https://api.tkpage.yolozs.com"
|
||||||
baseURL = "http://192.168.1.174:8101"
|
baseURL = "http://192.168.2.21:8101"
|
||||||
// baseURL = "https://crawlclient.api.yolozs.com"
|
// baseURL = "https://crawlclient.api.yolozs.com"
|
||||||
} else {
|
} else {
|
||||||
// 测试环境
|
// 测试环境
|
||||||
@@ -29,7 +29,7 @@ if (process.env.NODE_ENV === 'development') {
|
|||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
axios.interceptors.request.use((config) => {
|
axios.interceptors.request.use((config) => {
|
||||||
console.log("config", config)
|
// console.log("config", config)
|
||||||
const url = sliceUrl(config.url)
|
const url = sliceUrl(config.url)
|
||||||
console.log("url", url)
|
console.log("url", url)
|
||||||
if (!(config.url == 'doLogin' || config.url == 'get-id-by-name')) {
|
if (!(config.url == 'doLogin' || config.url == 'get-id-by-name')) {
|
||||||
@@ -50,7 +50,7 @@ axios.interceptors.request.use((config) => {
|
|||||||
axios.interceptors.response.use((response) => {
|
axios.interceptors.response.use((response) => {
|
||||||
console.log("response", response.data)
|
console.log("response", response.data)
|
||||||
if (response.data.code == 0) {
|
if (response.data.code == 0) {
|
||||||
console.log("response", response.data.data)
|
// console.log("response", response.data.data)
|
||||||
return response.data.data
|
return response.data.data
|
||||||
} else if (response.data.code == 40400) {
|
} else if (response.data.code == 40400) {
|
||||||
stopScript();
|
stopScript();
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ function switchLanguage(lang) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { getVersion, stopScript } = usePythonBridge();
|
const { getVersion, stopScript } = usePythonBridge();
|
||||||
let version = ref('0.0.0');
|
let version = ref('5.1.0');
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
stopScript();
|
stopScript();
|
||||||
@@ -156,7 +156,7 @@ const onSubmit = () => {
|
|||||||
password: formData.value.password,
|
password: formData.value.password,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
loading.close();
|
loading.close();
|
||||||
console.log(res)
|
// console.log(res)
|
||||||
setToken(res.tokenValue);
|
setToken(res.tokenValue);
|
||||||
setUser(res);
|
setUser(res);
|
||||||
router.push('/nav');
|
router.push('/nav');
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<el-table-column prop="invitationType" :label="$t('hostList.invitationType')" width="80">
|
<el-table-column prop="invitationType" :label="$t('hostList.invitationType')" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
|
||||||
<el-tag :type="scope.row.invitationType == 1 ? 'success' : 'warning'">
|
<el-tag :type="scope.row.invitationType == 1 ? 'success' : 'warning'" @click="getliveHost">
|
||||||
{{ scope.row.invitationType == 1 ? $t('hostList.invitationType1') : $t('hostList.invitationType2') }}
|
{{ scope.row.invitationType == 1 ? $t('hostList.invitationType1') : $t('hostList.invitationType2') }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// import { getToken, setToken, removeToken } from '@/utils/storage'
|
// import { getToken, setToken, removeToken } from '@/utils/storage'
|
||||||
import { tkhostdata, dicts, tkhostdetail, downList, getStaffList, managerhosts, upholdinfo, getCountryinfo, accountName } from '@/api/account';
|
import { tkhostdata, dicts, tkhostdetail, downList, getStaffList, managerhosts, upholdinfo, getCountryinfo, accountName, liveHostDetail } 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';
|
||||||
@@ -155,6 +155,7 @@ import { ref, reactive, onMounted } from 'vue';
|
|||||||
// import { color } from 'echarts';
|
// import { color } from 'echarts';
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
//py方法
|
//py方法
|
||||||
@@ -358,6 +359,17 @@ function handleClose(done) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getliveHost() {
|
||||||
|
liveHostDetail(
|
||||||
|
{
|
||||||
|
"hostsId": "1296peahh",
|
||||||
|
"tenantId": userInfo.value.tenantId
|
||||||
|
}
|
||||||
|
).then(res => {
|
||||||
|
console.log("直播间信息列表", JSON.stringify(res))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
//修改主播维护状态
|
//修改主播维护状态
|
||||||
// function handleSelectChange(event, data) {
|
// function handleSelectChange(event, data) {
|
||||||
|
|
||||||
@@ -396,14 +408,14 @@ function filterTag(value, row) {
|
|||||||
//获取国家
|
//获取国家
|
||||||
function getCountry() {
|
function getCountry() {
|
||||||
getCountryinfo({}).then(res => {
|
getCountryinfo({}).then(res => {
|
||||||
console.log(res)
|
// console.log(res)
|
||||||
res.forEach(item => {
|
res.forEach(item => {
|
||||||
if (item.countryGroupName) {
|
if (item.countryGroupName) {
|
||||||
options.value.push({ value: item.countryGroupName, label: item.countryGroupName })
|
options.value.push({ value: item.countryGroupName, label: item.countryGroupName })
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(options.value)
|
// console.log(options.value)
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log('getCountry', err)
|
console.log('getCountry', err)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -55,10 +55,23 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span class="center-justify"><img src="@/assets/worklogo.png">
|
<span class="center-justify"><img src="@/assets/worklogo.png">
|
||||||
{{ $t('workbenchesSetup.workbenches') }} </span>
|
{{ $t('workbenchesSetup.workbenches') }} </span>
|
||||||
<div style="margin-right: 120px;">{{ $t('workbenchesSetup.workbenches') }}:{{
|
<div class="card-header-right">
|
||||||
locale == 'zh' ? countryData : countryDataEN }}
|
|
||||||
<!-- <el-button class="reset-button" @click="reset">重置数据</el-button> -->
|
<span>
|
||||||
<!-- <el-button class="reset-button" @click="getIpInfo">刷新</el-button>s -->
|
{{ $t('workbenchesSetup.network') }}:{{ locale == 'zh' ? countryData : countryDataEN }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<img style="height: 20px;" v-if="isWifi" src="@/assets/wifi.png">
|
||||||
|
|
||||||
|
<span class="inline-country">
|
||||||
|
<span style="color: black;">指定国家</span>
|
||||||
|
<el-select v-model="country_info" class="country-select" placeholder="全部" size="small">
|
||||||
|
<el-option :label="'全部'" :value="'地区全部'" />
|
||||||
|
<el-option v-for="(item, index) in country_Lst" :key="index" :label="item"
|
||||||
|
:value="item" />
|
||||||
|
</el-select>
|
||||||
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -177,7 +190,8 @@ const { fetchDataConfig, fetchDataCount, loginBackStage, loginTikTok, backStagel
|
|||||||
let countryData = ref('');
|
let countryData = ref('');
|
||||||
//英文国家
|
//英文国家
|
||||||
let countryDataEN = ref('');
|
let countryDataEN = ref('');
|
||||||
|
let country_info = ref('全部');
|
||||||
|
let country_Lst = ref();
|
||||||
//获取主播数量的定时器
|
//获取主播数量的定时器
|
||||||
let getHostTimer = ref(null);
|
let getHostTimer = ref(null);
|
||||||
//获取查询次数定时器
|
//获取查询次数定时器
|
||||||
@@ -251,7 +265,7 @@ let hostNum = ref(0);
|
|||||||
let submitting = ref(true);
|
let submitting = ref(true);
|
||||||
let expiredTime = ref(null);
|
let expiredTime = ref(null);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
//从缓存获取数据
|
//从缓存获取数据
|
||||||
if (getNumData()) {
|
if (getNumData()) {
|
||||||
pyData.value = getNumData();
|
pyData.value = getNumData();
|
||||||
@@ -273,6 +287,14 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
checkVPN()
|
||||||
|
setInterval(async () => {
|
||||||
|
await checkVPN()
|
||||||
|
}, 1000 * 20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const getIpInfo = async () => {
|
const getIpInfo = async () => {
|
||||||
@@ -285,6 +307,13 @@ const getIpInfo = async () => {
|
|||||||
console.log('IP信息:', data.country);
|
console.log('IP信息:', data.country);
|
||||||
countryDataEN.value = data.country_name
|
countryDataEN.value = data.country_name
|
||||||
countryData.value = getCountryName(data.country);
|
countryData.value = getCountryName(data.country);
|
||||||
|
|
||||||
|
const url = `https://datasave.api.yolozs.com/api/save_data/country_info?countryName=${countryData.value}`;
|
||||||
|
|
||||||
|
const res = await fetch(url);
|
||||||
|
|
||||||
|
const countryres = await res.json();
|
||||||
|
country_Lst.value = countryres.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('请求出错:', error);
|
console.error('请求出错:', error);
|
||||||
ElMessageBox.prompt('请输入将要获取国家的中文名', '获取国家失败', {
|
ElMessageBox.prompt('请输入将要获取国家的中文名', '获取国家失败', {
|
||||||
@@ -294,8 +323,15 @@ const getIpInfo = async () => {
|
|||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
showCancelButton: false,
|
showCancelButton: false,
|
||||||
})
|
})
|
||||||
.then(({ value }) => {
|
.then(async ({ value }) => {
|
||||||
countryData.value = value
|
countryData.value = value
|
||||||
|
|
||||||
|
const url = `https://datasave.api.yolozs.com/api/save_data/country_info?countryName=${countryData.value}`;
|
||||||
|
|
||||||
|
const res = await fetch(url);
|
||||||
|
|
||||||
|
const countryres = await res.json();
|
||||||
|
country_Lst.value = countryres.data
|
||||||
})
|
})
|
||||||
// .catch(() => {
|
// .catch(() => {
|
||||||
// ElMessage({
|
// ElMessage({
|
||||||
@@ -368,6 +404,7 @@ const submit = () => {
|
|||||||
country: countryData.value,
|
country: countryData.value,
|
||||||
tenantId: getUser().tenantId,
|
tenantId: getUser().tenantId,
|
||||||
userId: getUser().id,
|
userId: getUser().id,
|
||||||
|
crawl_single_nation: country_info.value == '全部' ? '' : country_info.value
|
||||||
})).then((res) => {
|
})).then((res) => {
|
||||||
//开始计时器
|
//开始计时器
|
||||||
startTimer();
|
startTimer();
|
||||||
@@ -419,6 +456,8 @@ const unsubmit = () => {
|
|||||||
country: countryData.value,
|
country: countryData.value,
|
||||||
tenantId: getUser().tenantId,
|
tenantId: getUser().tenantId,
|
||||||
userId: getUser().id,
|
userId: getUser().id,
|
||||||
|
crawl_single_nation: country_info.value == '全部' ? '' : country_info.value
|
||||||
|
|
||||||
})).then((res) => {
|
})).then((res) => {
|
||||||
pauseTimer();
|
pauseTimer();
|
||||||
pyData.value.isStart = true;
|
pyData.value.isStart = true;
|
||||||
@@ -627,6 +666,34 @@ function timestampToTime(timestamp_ms) {
|
|||||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isWifi = ref(false);
|
||||||
|
const checkVPN = async () => {
|
||||||
|
try {
|
||||||
|
// 设置超时 5 秒钟
|
||||||
|
const timeout = new Promise((_, reject) =>
|
||||||
|
setTimeout(() => reject(new Error('请求超时')), 10000) // 10秒超时
|
||||||
|
);
|
||||||
|
|
||||||
|
// 使用 Promise.race 来进行超时控制
|
||||||
|
const response = await Promise.race([
|
||||||
|
fetch('https://www.google.com', { method: 'HEAD', mode: 'no-cors' }),
|
||||||
|
timeout
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 判断 fetch 请求是否成功
|
||||||
|
if (response && response.type === 'opaque') {
|
||||||
|
// ElMessage.success('VPN连接正常!');
|
||||||
|
isWifi.value = false;
|
||||||
|
} else {
|
||||||
|
ElMessage.error('VPN连接失败,无法访问网络。');
|
||||||
|
isWifi.value = true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 捕获超时错误或其他错误
|
||||||
|
ElMessage.error('VPN连接失败,无法访问网络。');
|
||||||
|
isWifi.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
@@ -730,6 +797,34 @@ function timestampToTime(timestamp_ms) {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
.card-header-right {
|
||||||
|
margin-right: 70px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
/* 各个块之间的间距 */
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* 整个右侧区域不换行 */
|
||||||
|
span {
|
||||||
|
color: #0013b9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-country {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
/* “指定国家” 和 select 的间距 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.country-select {
|
||||||
|
min-width: 120px;
|
||||||
|
/* 防止 select 太窄,文字被挤没 */
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-family: Source Han Sans SC;
|
font-family: Source Han Sans SC;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@@ -752,12 +847,7 @@ function timestampToTime(timestamp_ms) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #606266;
|
|
||||||
}
|
|
||||||
|
|
||||||
.open-login {
|
.open-login {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
|
|||||||
Reference in New Issue
Block a user