feat: add force refresh button to source/collection cards

- Backend: preview handlers accept forceRefresh in request body
- Frontend: Sources & Collections cards get a refresh button that
  bypasses cache and re-fetches from remote
This commit is contained in:
2026-07-28 21:42:12 +08:00
parent feafb19714
commit 55ab656606
8 changed files with 95 additions and 40 deletions
+4 -2
View File
@@ -71,8 +71,10 @@ export const deleteRecycleEntry = (id) => api.delete(`/recycle-bin/${id}`)
export const restoreRecycleEntry = (id) => api.post(`/recycle-bin/${id}/restore`)
// Preview
export const previewSource = (data) => api.post('/preview/source', data)
export const previewCollection = (data) => api.post('/preview/collection', data)
export const previewSource = (data, forceRefresh = false) =>
api.post('/preview/source', forceRefresh ? { ...data, forceRefresh: true } : data)
export const previewCollection = (data, forceRefresh = false) =>
api.post('/preview/collection', forceRefresh ? { ...data, forceRefresh: true } : data)
// Download links
export const getLinkSource = (name, target) => api.get(`/link/source/${name}`, { params: target ? { target } : {} })
+22
View File
@@ -26,6 +26,10 @@
</div>
</div>
<div class="flex gap-1 ml-3">
<button class="px-2.5 py-1 text-xs rounded hover:bg-blue-50 text-blue-600 whitespace-nowrap"
:disabled="!!egressLoadingId || refreshingId === col.id" @click.stop="refreshCollection(col)">
{{ refreshingId === col.id ? '刷新中...' : '刷新' }}
</button>
<button class="px-2.5 py-1 text-xs rounded hover:bg-blue-50 text-blue-600 whitespace-nowrap"
:disabled="!!egressLoadingId" @click.stop="probeCollectionEgress(col)">
{{ egressLoadingId === col.id ? `探测 ${egressProgress}` : '探测出口' }}
@@ -168,6 +172,7 @@ const expandedLoading = ref(false)
const expandedData = ref(null)
const egressLoadingId = ref('')
const egressProgress = ref('')
const refreshingId = ref('')
const toast = ref(null)
const nodeCounts = reactive({})
const confirmDialog = ref({ show: false, title: '', message: '', danger: false, action: null })
@@ -325,6 +330,23 @@ async function copyNodeLink(node) {
}
}
async function refreshCollection(col) {
if (refreshingId.value) return
refreshingId.value = col.id
try {
const res = await previewCollection(col, true)
nodeCounts[col.id] = countsFromPreview(res.data)
if (expandedCollectionId.value === col.id) {
expandedData.value = res.data
}
showToast('已刷新')
} catch (e) {
showToast(e.message, 'error')
} finally {
refreshingId.value = ''
}
}
async function probeCollectionEgress(col) {
if (egressLoadingId.value) return
egressLoadingId.value = col.id
+22
View File
@@ -30,6 +30,10 @@
<p v-if="flowSummary(src)" class="text-xs text-gray-500 mt-1 truncate">{{ flowSummary(src) }}</p>
</div>
<div class="flex gap-1 ml-3">
<button class="px-2.5 py-1 text-xs rounded hover:bg-blue-50 text-blue-600 whitespace-nowrap"
:disabled="!!egressLoadingId || refreshingId === src.id" @click.stop="refreshSource(src)">
{{ refreshingId === src.id ? '刷新中...' : '刷新' }}
</button>
<button class="px-2.5 py-1 text-xs rounded hover:bg-blue-50 text-blue-600 whitespace-nowrap"
:disabled="!!egressLoadingId" @click.stop="probeSourceEgress(src)">
{{ egressLoadingId === src.id ? `探测 ${egressProgress}` : '探测出口' }}
@@ -203,6 +207,7 @@ const expandedLoading = ref(false)
const expandedData = ref(null)
const egressLoadingId = ref('')
const egressProgress = ref('')
const refreshingId = ref('')
const nodeCounts = reactive({})
const flowInfos = reactive({})
const toast = ref(null)
@@ -428,6 +433,23 @@ async function copyNodeLink(node) {
}
}
async function refreshSource(src) {
if (refreshingId.value) return
refreshingId.value = src.id
try {
const res = await previewSource(sourcePreviewPayload(src), true)
nodeCounts[src.id] = countsFromPreview(res.data)
if (expandedSourceId.value === src.id) {
expandedData.value = res.data
}
showToast('已刷新')
} catch (e) {
showToast(e.message, 'error')
} finally {
refreshingId.value = ''
}
}
async function probeSourceEgress(src) {
if (egressLoadingId.value) return
egressLoadingId.value = src.id