feat: 添加单个数据源手动更新功能
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import { IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonBadge, IonSpinner, IonRefresher, IonRefresherContent, RefresherEventDetail } from '@ionic/vue'
|
import { IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonBadge, IonSpinner, IonRefresher, IonRefresherContent, IonButton, RefresherEventDetail } from '@ionic/vue'
|
||||||
import { getCrawlInfoStats } from '@/utils/api'
|
import { getCrawlInfoStats, crawlSingleSource } from '@/utils/api'
|
||||||
import type { CrawlInfoStat } from '@/types'
|
import type { CrawlInfoStat } from '@/types'
|
||||||
|
|
||||||
const crawlStats = ref<CrawlInfoStat[]>([])
|
const crawlStats = ref<CrawlInfoStat[]>([])
|
||||||
const loading = ref<boolean>(true)
|
const loading = ref<boolean>(true)
|
||||||
const error = ref<string>('')
|
const error = ref<string>('')
|
||||||
|
const updatingSources = ref<Set<string>>(new Set())
|
||||||
|
|
||||||
const loadCrawlStats = async () => {
|
const loadCrawlStats = async () => {
|
||||||
try {
|
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 => {
|
const getStatusText = (stat: CrawlInfoStat): string => {
|
||||||
if (stat.error) {
|
if (stat.error) {
|
||||||
return '出错'
|
return '出错'
|
||||||
@@ -142,15 +161,27 @@ defineExpose({
|
|||||||
<IonCardContent class="crawl-card-content">
|
<IonCardContent class="crawl-card-content">
|
||||||
<div class="crawl-header">
|
<div class="crawl-header">
|
||||||
<span class="source-name">{{ stat.source }}</span>
|
<span class="source-name">{{ stat.source }}</span>
|
||||||
<IonBadge
|
<div class="header-actions">
|
||||||
:style="{
|
<IonBadge
|
||||||
backgroundColor: getStatusColor(stat),
|
:style="{
|
||||||
color: getStatusTextColor(stat)
|
backgroundColor: getStatusColor(stat),
|
||||||
}"
|
color: getStatusTextColor(stat)
|
||||||
class="status-badge"
|
}"
|
||||||
>
|
class="status-badge"
|
||||||
{{ getStatusText(stat) }}
|
>
|
||||||
</IonBadge>
|
{{ 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>
|
||||||
<div class="crawl-details">
|
<div class="crawl-details">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
@@ -264,6 +295,12 @@ defineExpose({
|
|||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.status-badge {
|
.status-badge {
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@@ -271,6 +308,15 @@ defineExpose({
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.update-button {
|
||||||
|
--padding-start: 8px;
|
||||||
|
--padding-end: 8px;
|
||||||
|
--padding-top: 4px;
|
||||||
|
--padding-bottom: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
.crawl-details {
|
.crawl-details {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ export function getCrawlInfoStats(): Promise<CrawlInfoStat[]> {
|
|||||||
return api.get('/api/bids/crawl-info-stats').then(res => res.data)
|
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