达人工作台完善

This commit is contained in:
2026-04-28 16:39:59 +08:00
parent 54402b0dd4
commit d5d6495cba
4 changed files with 88 additions and 9 deletions

View File

@@ -21,6 +21,22 @@
</div>
<div class="flex flex-wrap items-end gap-4">
<div class="flex flex-col gap-1">
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider">国家</label>
<div
class="flex items-center gap-2 rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-700">
<span>{{ countryData || '未识别' }}</span>
<span class="rounded bg-slate-100 px-2 py-0.5 text-xs text-slate-500">{{ regionCode || '--' }}</span>
<button @click="editCountry" :disabled="isRunning || isRefreshingCountry"
class="rounded-md p-1 text-slate-500 transition-colors hover:bg-slate-100 disabled:opacity-50">
<span class="material-icons-round text-base">edit</span>
</button>
<button @click="refreshCountryFn" :disabled="isRunning || isRefreshingCountry"
class="rounded-md p-1 text-slate-500 transition-colors hover:bg-slate-100 disabled:opacity-50">
<span class="material-icons-round text-base" :class="{ 'animate-spin': isRefreshingCountry }">refresh</span>
</button>
</div>
</div>
<div class="flex flex-col gap-1">
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider">最小粉丝数</label>
<el-input v-model="crawlForm.fansMin" placeholder="最小值" style="width: 150px" type="number"
@@ -33,9 +49,6 @@
</div>
</div>
<div class="mt-4 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-700">
当前仓库里还没有达人爬虫的后端启动接口这里先保留前端配置和任务态等后端接口接入后再把参数真正传下去
</div>
</section>
<section class="rounded-2xl border border-slate-100 bg-white p-5">
@@ -119,6 +132,9 @@ import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
import { ElMessage } from 'element-plus';
import { getUser } from '@/utils/storage';
import { expertInfoPage } from '@/api/account';
import { useCountryInfo } from '@/composables/useCountryInfo';
import { CountryCode } from '@/utils/countryUtil';
import { usePythonBridge } from '@/utils/pythonBridge';
const userInfo = ref({});
const tenantId = ref('');
@@ -135,11 +151,14 @@ const tableData = ref([]);
const isRunning = ref(false);
const elapsedSeconds = ref(0);
const elapsedTimerId = ref(null);
const { countryData, isLoading: isRefreshingCountry, initCountryInfo, refreshCountry, showEditCountryDialog } = useCountryInfo();
const { controlExpertCapture } = usePythonBridge();
const stats = computed(() => ({
total: total.value,
pageCount: tableData.value.length,
}));
const regionCode = computed(() => resolveRegionCode(countryData.value));
const formattedElapsed = computed(() => {
const hours = Math.floor(elapsedSeconds.value / 3600);
@@ -152,6 +171,7 @@ onMounted(() => {
userInfo.value = getUser() || {};
tenantId.value = String(userInfo.value?.tenantId || '');
queryDate.value = buildTodayText();
void initCountryInfo((key) => key);
void loadList();
});
@@ -176,6 +196,15 @@ function normalizeNumber(value) {
return Number.isFinite(parsed) ? parsed : undefined;
}
function resolveRegionCode(countryName) {
if (!countryName) {
return '';
}
const matched = Object.entries(CountryCode).find(([code, name]) => code.length === 2 && name === countryName);
return matched?.[0] || '';
}
function formatDateTime(value) {
if (!value) {
return '';
@@ -229,9 +258,23 @@ function validateCrawlRange() {
return false;
}
if (!regionCode.value) {
ElMessage.error('当前国家无法转换为地区代码,请先修改国家');
return false;
}
return true;
}
function buildCapturePayload(isStart) {
return {
region: regionCode.value,
MinFollowerCount: normalizeNumber(crawlForm.value.fansMin) ?? 0,
MaxFollowerCount: normalizeNumber(crawlForm.value.fansMax) ?? 0,
isStart,
};
}
async function loadList() {
if (!tenantId.value) {
tableData.value = [];
@@ -270,7 +313,7 @@ function stopElapsedTimer() {
}
}
function handleStart() {
async function handleStart() {
if (!tenantId.value) {
ElMessage.error('缺少 tenantId无法启动达人工作台');
return;
@@ -280,17 +323,41 @@ function handleStart() {
return;
}
const result = await controlExpertCapture(JSON.stringify(buildCapturePayload(true)));
if (!result?.success) {
ElMessage.error(result?.error || '启动达人爬虫失败');
return;
}
isRunning.value = true;
startElapsedTimer();
ElMessage.success('达人工作台已进入运行');
ElMessage.success('达人工作台已开始运行');
}
function handleStop() {
async function handleStop() {
const result = await controlExpertCapture(JSON.stringify(buildCapturePayload(false)));
if (!result?.success) {
ElMessage.error(result?.error || '停止达人爬虫失败');
return;
}
isRunning.value = false;
stopElapsedTimer();
ElMessage.success('达人工作台已停止');
}
async function refreshCountryFn() {
await refreshCountry((key) => key);
}
async function editCountry() {
try {
await showEditCountryDialog((key) => key);
} catch {
// 用户取消
}
}
async function handleSearch() {
page.value = 1;
await loadList();