Files
diary-news/frontend/src/views/Sources.vue

81 lines
2.6 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { NCard, NDataTable, NTag, NSpace, NText, NButton, useMessage } from 'naive-ui'
import { sourcesApi, adminApi, type Source } from '@/api/articles'
import { useAuthStore } from '@/stores/auth'
import dayjs from 'dayjs'
const auth = useAuthStore()
const message = useMessage()
const sources = ref<Source[]>([])
const health = ref<any[]>([])
const loading = ref(false)
async function load() {
sources.value = await sourcesApi.list()
if (auth.isOwner) {
try { health.value = await adminApi.health() } catch { /* noop */ }
}
}
async function triggerRefresh(id: number) {
try {
await adminApi.refresh(id)
message.success('已加入抓取队列')
} catch (e: any) {
message.error(e?.response?.data?.title || '触发失败')
}
}
function fmtTime(s?: string | null) {
if (!s) return '—'
return dayjs(s).format('YYYY-MM-DD HH:mm')
}
const columns = [
{ title: '名称', key: 'name' },
{ title: '源', key: 'slug' },
{ title: '地区', key: 'region' },
{ title: '优先级', key: 'priority' },
{
title: '状态', key: 'enabled',
render: (row: Source) => h(NTag, { type: row.enabled ? 'success' : 'default', size: 'small' }, () => row.enabled ? '启用' : '停用'),
},
{ title: '抓取间隔', key: 'fetch_interval_min', render: (r: Source) => `${r.fetch_interval_min}m` },
{ title: '上次抓取', key: 'last_fetched_at', render: (r: Source) => fmtTime(r.last_fetched_at) },
{ title: '上次状态', key: 'last_status' },
{
title: '操作', key: 'action', width: 120,
render: (row: Source) => h(NSpace, {}, () => [
auth.isOwner && row.enabled
? h(NButton, { size: 'small', onClick: () => triggerRefresh(row.id) }, () => '立即抓取')
: null,
]),
},
]
import { h } from 'vue'
const healthColumns = [
{ title: '源', key: 'slug' },
{ title: '24h 新增', key: 'article_count_24h' },
{ title: '连续失败', key: 'consecutive_failures' },
{ title: '当前间隔', key: 'fetch_interval_min', render: (r: any) => `${r.fetch_interval_min}m` },
{ title: '上次', key: 'last_fetched_at', render: (r: any) => fmtTime(r.last_fetched_at) },
{ title: '状态', key: 'last_status' },
]
onMounted(load)
</script>
<template>
<NSpace vertical>
<NCard title="采集源(只读)">
<NDataTable :columns="columns" :data="sources" :bordered="false" :pagination="false" />
</NCard>
<NCard v-if="auth.isOwner" title="源健康(Owner)">
<NDataTable :columns="healthColumns" :data="health" :bordered="false" :pagination="false" />
</NCard>
</NSpace>
</template>