feat: add gallery pagination, dynamic progress colors, and UX fixes

- Replace infinite scroll with page-based navigation in gallery
- Add dynamic progress color (blue→amber→red) in encyclopedia
- Fix timeline not returning to realtime when closing in archive mode
- Simplify image detail modal close button styling
- Add web-design-reviewer skill
This commit is contained in:
2026-05-24 17:08:39 +08:00
parent 09841c06a6
commit 0e063c3abb
5 changed files with 134 additions and 85 deletions
+23 -3
View File
@@ -20,9 +20,25 @@ const rarityMeta = {
rare: { label: '罕见', chip: 'bg-rose-100 text-rose-700 border-rose-200', glow: 'from-rose-100 to-white' },
} satisfies Record<CloudType['rarity'], { label: string; chip: string; glow: string }>
function lerpHex(a: string, b: string, t: number) {
const ah = parseInt(a.slice(1), 16)
const bh = parseInt(b.slice(1), 16)
const r = Math.round(((ah >> 16) & 0xff) + (((bh >> 16) & 0xff) - ((ah >> 16) & 0xff)) * t)
const g = Math.round(((ah >> 8) & 0xff) + (((bh >> 8) & 0xff) - ((ah >> 8) & 0xff)) * t)
const bv = Math.round((ah & 0xff) + ((bh & 0xff) - (ah & 0xff)) * t)
return `#${((r << 16) | (g << 8) | bv).toString(16).padStart(6, '0')}`
}
function progressColor(percent: number) {
const t = Math.min(1, Math.max(0, percent / 100))
if (t <= 0.5) return lerpHex('#0ea5e9', '#f59e0b', t * 2)
return lerpHex('#f59e0b', '#ef4444', (t - 0.5) * 2)
}
const totalTypes = computed(() => encyclopediaStore.cloudTypes.length || 10)
const unlockedCount = computed(() => (authStore.isLoggedIn ? encyclopediaStore.unlockedCount : 0))
const progressText = computed(() => `${unlockedCount.value}/${totalTypes.value}`)
const currentProgressColor = computed(() => progressColor(authStore.isLoggedIn ? encyclopediaStore.unlockPercent : 0))
function isUnlocked(cloudTypeId: number) {
return authStore.isLoggedIn && encyclopediaStore.isUnlocked(cloudTypeId)
@@ -80,9 +96,12 @@ onMounted(async () => {
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-slate-500">当前进度</p>
<p class="mt-1 text-3xl font-bold text-slate-900">{{ progressText }}</p>
<p class="mt-1 text-3xl font-bold" :style="{ color: currentProgressColor }">{{ progressText }}</p>
</div>
<div class="flex h-16 w-16 items-center justify-center border border-slate-900 bg-slate-900 text-xl font-semibold text-white">
<div
class="flex h-16 w-16 items-center justify-center border text-xl font-semibold text-white transition-colors duration-500"
:style="{ backgroundColor: currentProgressColor, borderColor: currentProgressColor }"
>
{{ authStore.isLoggedIn ? encyclopediaStore.unlockPercent : 0 }}%
</div>
</div>
@@ -92,8 +111,9 @@ onMounted(async () => {
type="line"
:show-indicator="false"
:percentage="authStore.isLoggedIn ? encyclopediaStore.unlockPercent : 0"
color="{stops:['#0ea5e9','#f59e0b']}"
:color="{ stops: ['#0ea5e9', currentProgressColor] }"
:height="12"
rail-color="#e2e8f0"
/>
<p class="mt-4 text-sm text-slate-500">