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:
-37
File diff suppressed because one or more lines are too long
+37
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sub-Store</title>
|
||||
<script src="/config.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CgvGHl8V.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-Du03v-Eh.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-s7owp4VX.css">
|
||||
</head>
|
||||
<body class="bg-gray-50 text-gray-900">
|
||||
|
||||
@@ -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 } : {} })
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -620,6 +620,13 @@ func getMapValue(v any) map[string]any {
|
||||
return map[string]any{}
|
||||
}
|
||||
|
||||
func getBoolValue(v any) bool {
|
||||
if b, ok := v.(bool); ok {
|
||||
return b
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getStringArray(v any) []string {
|
||||
if arr, ok := v.([]any); ok {
|
||||
result := make([]string, 0, len(arr))
|
||||
|
||||
@@ -183,6 +183,7 @@ func (d *Deps) HandlePreviewSource(c fiber.Ctx) error {
|
||||
Target: "json",
|
||||
Settings: settings,
|
||||
RequestUserAgent: c.Get("User-Agent"),
|
||||
ForceRefresh: getBoolValue(input["forceRefresh"]),
|
||||
CacheRepo: d.CacheRepo,
|
||||
ProxyURL: d.Cfg.Fetcher.ProxyURL,
|
||||
})
|
||||
@@ -212,6 +213,7 @@ func (d *Deps) HandlePreviewCollection(c fiber.Ctx) error {
|
||||
TemplateConfig: d.getTemplateConfig(rec.TemplateId),
|
||||
Settings: settings,
|
||||
RequestUserAgent: c.Get("User-Agent"),
|
||||
ForceRefresh: getBoolValue(input["forceRefresh"]),
|
||||
CacheRepo: d.CacheRepo,
|
||||
ProxyURL: d.Cfg.Fetcher.ProxyURL,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user