@@ -100,7 +207,19 @@ function ttlText(value: number | string) {
{{ m.enabled ? '已启用' : '已停用' }}
- | {{ ttlText(m.cacheTTL) }} |
+
+
+
+
+ 该镜像不缓存
+ |
diff --git a/web/src/views/Search.vue b/web/src/views/Search.vue
index ba0a85e..11ee9ae 100644
--- a/web/src/views/Search.vue
+++ b/web/src/views/Search.vue
@@ -16,6 +16,7 @@ const selectedRegistry = ref('')
const page = ref(1)
const perPage = 10
const hasMore = ref(false)
+let searchSeq = 0
onMounted(async () => {
try {
@@ -44,18 +45,23 @@ async function doSearch() {
}
async function fetchResults() {
+ const seq = ++searchSeq
loading.value = true
errorMsg.value = ''
try {
const data = await searchMirrors(query.value, selectedRegistry.value, page.value, perPage)
+ // 丢弃过期请求的结果,避免快速翻页/换词时旧响应覆盖新数据
+ if (seq !== searchSeq) return
results.value = data.results || []
hasMore.value = data.has_more ?? data.hasMore ?? false
} catch (e: any) {
+ if (seq !== searchSeq) return
results.value = []
hasMore.value = false
errorMsg.value = e.response?.statusText || '搜索失败,请稍后重试'
+ } finally {
+ if (seq === searchSeq) loading.value = false
}
- loading.value = false
}
function nextPage() {
diff --git a/web/src/views/Settings.vue b/web/src/views/Settings.vue
index d76318e..7569240 100644
--- a/web/src/views/Settings.vue
+++ b/web/src/views/Settings.vue
@@ -37,10 +37,22 @@ onMounted(async () => {
async function saveRateLimit() {
rlSaving.value = true
rlMsg.value = ''
+ // 与后端校验保持一致:rate 必须为正、interval 必须可解析
+ if (!Number.isInteger(rlRate.value) || rlRate.value <= 0) {
+ rlMsg.value = '最大请求数必须为正整数'
+ rlSaving.value = false
+ return
+ }
+ const interval = rlInterval.value.trim()
+ if (!/^\d+(ms|s|m|h|d)$/.test(interval)) {
+ rlMsg.value = '时间窗口格式无效(如 3h、30m、1d)'
+ rlSaving.value = false
+ return
+ }
try {
const wl = rlWhitelist.value.split(',').map(s => s.trim()).filter(Boolean)
const bl = rlBlacklist.value.split(',').map(s => s.trim()).filter(Boolean)
- const res = await updateRateLimitConfig({ enabled: rlEnabled.value, rate: rlRate.value, interval: rlInterval.value, whitelist: wl, blacklist: bl })
+ const res = await updateRateLimitConfig({ enabled: rlEnabled.value, rate: rlRate.value, interval, whitelist: wl, blacklist: bl })
rlEnabled.value = res.enabled
rlRate.value = res.rate
rlInterval.value = res.interval || rlInterval.value
|