feat: 添加单个数据源手动更新功能
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonBadge, IonSpinner, IonRefresher, IonRefresherContent, RefresherEventDetail } from '@ionic/vue'
|
||||
import { getCrawlInfoStats } from '@/utils/api'
|
||||
import { IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonBadge, IonSpinner, IonRefresher, IonRefresherContent, IonButton, RefresherEventDetail } from '@ionic/vue'
|
||||
import { getCrawlInfoStats, crawlSingleSource } from '@/utils/api'
|
||||
import type { CrawlInfoStat } from '@/types'
|
||||
|
||||
const crawlStats = ref<CrawlInfoStat[]>([])
|
||||
const loading = ref<boolean>(true)
|
||||
const error = ref<string>('')
|
||||
const updatingSources = ref<Set<string>>(new Set())
|
||||
|
||||
const loadCrawlStats = async () => {
|
||||
try {
|
||||
@@ -22,6 +23,24 @@ const loadCrawlStats = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleUpdateSource = async (sourceName: string) => {
|
||||
if (updatingSources.value.has(sourceName)) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
updatingSources.value.add(sourceName)
|
||||
await crawlSingleSource(sourceName)
|
||||
// 更新成功后重新加载统计数据
|
||||
await loadCrawlStats()
|
||||
} catch (err: any) {
|
||||
console.error(`更新 ${sourceName} 失败:`, err)
|
||||
alert(`更新失败: ${err.message || err}`)
|
||||
} finally {
|
||||
updatingSources.value.delete(sourceName)
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusText = (stat: CrawlInfoStat): string => {
|
||||
if (stat.error) {
|
||||
return '出错'
|
||||
@@ -142,15 +161,27 @@ defineExpose({
|
||||
<IonCardContent class="crawl-card-content">
|
||||
<div class="crawl-header">
|
||||
<span class="source-name">{{ stat.source }}</span>
|
||||
<IonBadge
|
||||
:style="{
|
||||
backgroundColor: getStatusColor(stat),
|
||||
color: getStatusTextColor(stat)
|
||||
}"
|
||||
class="status-badge"
|
||||
>
|
||||
{{ getStatusText(stat) }}
|
||||
</IonBadge>
|
||||
<div class="header-actions">
|
||||
<IonBadge
|
||||
:style="{
|
||||
backgroundColor: getStatusColor(stat),
|
||||
color: getStatusTextColor(stat)
|
||||
}"
|
||||
class="status-badge"
|
||||
>
|
||||
{{ getStatusText(stat) }}
|
||||
</IonBadge>
|
||||
<IonButton
|
||||
size="small"
|
||||
fill="outline"
|
||||
:disabled="updatingSources.has(stat.source)"
|
||||
@click="handleUpdateSource(stat.source)"
|
||||
class="update-button"
|
||||
>
|
||||
<span v-if="updatingSources.has(stat.source)">更新中...</span>
|
||||
<span v-else>更新</span>
|
||||
</IonButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="crawl-details">
|
||||
<div class="detail-item">
|
||||
@@ -264,6 +295,12 @@ defineExpose({
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
@@ -271,6 +308,15 @@ defineExpose({
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.update-button {
|
||||
--padding-start: 8px;
|
||||
--padding-end: 8px;
|
||||
--padding-top: 4px;
|
||||
--padding-bottom: 4px;
|
||||
font-size: 12px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.crawl-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -55,6 +55,13 @@ export function getCrawlInfoStats(): Promise<CrawlInfoStat[]> {
|
||||
return api.get('/api/bids/crawl-info-stats').then(res => res.data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 爬取单个数据源
|
||||
*/
|
||||
export function crawlSingleSource(sourceName: string): Promise<any> {
|
||||
return api.post(`/api/crawler/crawl/${encodeURIComponent(sourceName)}`).then(res => res.data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换置顶状态
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user