feat: 更改加载时间

This commit is contained in:
王天骄
2026-06-15 17:55:07 +08:00
parent 9b95789595
commit 4c130cee9d
3 changed files with 148 additions and 16 deletions
+11 -2
View File
@@ -141,7 +141,13 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { fetchCaseListPage, type CaseListSource, type CaseMode, type ClinicalCase } from '../../api/cases'
import {
fetchCaseListPage,
takePrefetchedCaseList,
type CaseListSource,
type CaseMode,
type ClinicalCase
} from '../../api/cases'
import { createHomeNavigator, createProfileOpener, createSettingsOpener } from '../../api/navigation'
const emit = defineEmits<{
@@ -284,9 +290,12 @@ async function loadCases(page = 1) {
loadingMore.value = !isFirstPage
loadFailed.value = false
errorMessage.value = ''
const query = buildQuery(page)
try {
const result = await fetchCaseListPage(source.value, buildQuery(page))
const result = isFirstPage
? takePrefetchedCaseList(source.value, query) || await fetchCaseListPage(source.value, query)
: await fetchCaseListPage(source.value, query)
if (seq !== requestSeq) return
cases.value = isFirstPage ? result.results : [...cases.value, ...result.results]
+75 -14
View File
@@ -64,7 +64,13 @@
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import type { CaseListSource } from '../../api/cases'
import {
clearPrefetchedCaseList,
fetchCaseListPage,
savePrefetchedCaseList,
type CaseListQuery,
type CaseListSource
} from '../../api/cases'
import { fetchMatchingProfile, type MatchingProfile } from '../../api/matching'
type Particle = {
@@ -86,13 +92,22 @@ const source = ref<CaseListSource>('recommended')
let particleId = 0
let particleTimer: ReturnType<typeof setInterval> | null = null
let progressTimer: ReturnType<typeof setInterval> | null = null
const MATCHING_DURATION_MS = 10000
let navigationTimer: ReturnType<typeof setTimeout> | null = null
let minDurationFinished = false
let prefetchFinished = false
let hasRedirected = false
let isActive = false
const MIN_MATCHING_DURATION_MS = 3000
const PROGRESS_INTERVAL_MS = 100
const PREFETCH_QUERY: CaseListQuery = {
page: 1,
page_size: 10
}
function loadMatchingProfile() {
fetchMatchingProfile().then(result => {
Object.assign(profile, result)
startProgress()
})
}
@@ -133,20 +148,62 @@ function startProgress() {
const startedAt = Date.now()
progressTimer = setInterval(() => {
const elapsed = Date.now() - startedAt
const ratio = Math.min(1, elapsed / MATCHING_DURATION_MS)
progress.value = Math.round(profile.progressTarget * ratio)
if (ratio >= 1) {
if (progressTimer) clearInterval(progressTimer)
progressTimer = null
uni.redirectTo({
url: `/pages/cases/cases?source=${encodeURIComponent(source.value)}`
})
return
}
const minimumRatio = Math.min(1, elapsed / MIN_MATCHING_DURATION_MS)
const waitBonus = elapsed > MIN_MATCHING_DURATION_MS
? Math.min(7, Math.floor((elapsed - MIN_MATCHING_DURATION_MS) / 1000))
: 0
progress.value = Math.min(99, Math.round(profile.progressTarget * minimumRatio + waitBonus))
}, PROGRESS_INTERVAL_MS)
}
async function startMatchingFlow() {
clearPrefetchedCaseList()
minDurationFinished = false
prefetchFinished = false
hasRedirected = false
startProgress()
wait(MIN_MATCHING_DURATION_MS).then(() => {
minDurationFinished = true
redirectWhenReady()
})
try {
const page = await fetchCaseListPage(source.value, PREFETCH_QUERY)
if (!isActive) return
savePrefetchedCaseList({
source: source.value,
query: PREFETCH_QUERY,
page,
cachedAt: Date.now()
})
} catch {
// The case list page will retry and show its own error state if needed.
} finally {
prefetchFinished = true
redirectWhenReady()
}
}
function redirectWhenReady() {
if (!isActive || hasRedirected || !minDurationFinished || !prefetchFinished) return
hasRedirected = true
progress.value = 100
if (progressTimer) clearInterval(progressTimer)
progressTimer = null
navigationTimer = setTimeout(() => {
uni.redirectTo({
url: `/pages/cases/cases?source=${encodeURIComponent(source.value)}`
})
}, 120)
}
function wait(ms: number) {
return new Promise<void>(resolve => {
setTimeout(resolve, ms)
})
}
onLoad(query => {
const querySource = query?.source
if (isCaseListSource(querySource)) {
@@ -155,13 +212,17 @@ onLoad(query => {
})
onMounted(() => {
isActive = true
loadMatchingProfile()
startParticles()
startMatchingFlow()
})
onUnmounted(() => {
isActive = false
if (particleTimer) clearInterval(particleTimer)
if (progressTimer) clearInterval(progressTimer)
if (navigationTimer) clearTimeout(navigationTimer)
})
function isCaseListSource(value: unknown): value is CaseListSource {