feat: 更改加载时间
This commit is contained in:
+11
-2
@@ -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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user