refactor: extract EncyclopediaProgressCard component and limit map pitch
- Create EncyclopediaProgressCard with dynamic progress color, reuse in encyclopedia and profile pages to unify styling - Add skyColor and maxPitch to AMap 3D view to reduce empty tile area when tilting - Extend AMap type declarations for skyColor, maxPitch, getPitch, getRotation
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { NAlert, NCard, NEmpty, NIcon, NProgress, NSkeleton } from 'naive-ui'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { NAlert, NCard, NEmpty, NIcon, NSkeleton } from 'naive-ui'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useEncyclopediaStore } from '@/stores/encyclopedia'
|
||||
import EncyclopediaProgressCard from '@/components/cloud/EncyclopediaProgressCard.vue'
|
||||
import { Lock } from '@vicons/tabler'
|
||||
import type { CloudType } from '@/types/database'
|
||||
|
||||
@@ -20,26 +21,6 @@ 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)
|
||||
}
|
||||
@@ -92,39 +73,12 @@ onMounted(async () => {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<NCard class="border border-white/80 bg-white/85 shadow-sm backdrop-blur" :bordered="false">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-slate-500">当前进度</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 text-xl font-semibold text-white transition-colors duration-500"
|
||||
:style="{ backgroundColor: currentProgressColor, borderColor: currentProgressColor }"
|
||||
>
|
||||
{{ authStore.isLoggedIn ? encyclopediaStore.unlockPercent : 0 }}%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NProgress
|
||||
class="mt-5"
|
||||
type="line"
|
||||
:show-indicator="false"
|
||||
:percentage="authStore.isLoggedIn ? encyclopediaStore.unlockPercent : 0"
|
||||
:color="{ stops: ['#0ea5e9', currentProgressColor] }"
|
||||
:height="12"
|
||||
rail-color="#e2e8f0"
|
||||
/>
|
||||
|
||||
<p class="mt-4 text-sm text-slate-500">
|
||||
<template v-if="authStore.isLoggedIn">
|
||||
已解锁 {{ unlockedCount }} 枚徽章,还差 {{ Math.max(totalTypes - unlockedCount, 0) }} 枚。
|
||||
</template>
|
||||
<template v-else>
|
||||
登录后可同步你的个人图鉴进度。
|
||||
</template>
|
||||
</p>
|
||||
</NCard>
|
||||
<EncyclopediaProgressCard
|
||||
:unlocked-count="authStore.isLoggedIn ? encyclopediaStore.unlockedCount : 0"
|
||||
:total-count="encyclopediaStore.cloudTypes.length || 10"
|
||||
:percent="encyclopediaStore.unlockPercent"
|
||||
:is-logged-in="authStore.isLoggedIn"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -409,6 +409,8 @@ onMounted(async () => {
|
||||
mapStyle: 'amap://styles/normal',
|
||||
features: ['bg', 'road', 'building', 'point'],
|
||||
resizeEnable: true,
|
||||
skyColor: '#c8dce8',
|
||||
maxPitch: 70,
|
||||
} as AMap.MapOptions)
|
||||
|
||||
mapInst.addControl(new AMapLib.Scale())
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { NAlert, NButton, NCard, NDropdown, NEmpty, NIcon, NProgress, NSkeleton, NTag, useMessage } from 'naive-ui'
|
||||
import { NAlert, NButton, NCard, NDropdown, NEmpty, NIcon, NSkeleton, NTag, useMessage } from 'naive-ui'
|
||||
import EncyclopediaProgressCard from '@/components/cloud/EncyclopediaProgressCard.vue'
|
||||
import { Settings } from '@vicons/tabler'
|
||||
import CloudEditModal, { type CloudEditFormValue } from '@/components/cloud/CloudEditModal.vue'
|
||||
import ImageDetailModal from '@/components/cloud/ImageDetailModal.vue'
|
||||
@@ -536,33 +537,18 @@ watch(selectedUploadDate, async newValue => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NCard class="border border-white/80 bg-white/85 shadow-sm backdrop-blur" :bordered="false">
|
||||
<template v-if="isOwnProfile">
|
||||
<p class="text-sm text-slate-500">图鉴进度</p>
|
||||
<div class="mt-3 flex items-end justify-between gap-4">
|
||||
<div>
|
||||
<p class="text-3xl font-bold text-slate-900">{{ encyclopediaStore.unlockProgress }}</p>
|
||||
<p class="mt-2 text-sm text-slate-500">已解锁 {{ encyclopediaStore.unlockedCount }} 种基础云型</p>
|
||||
</div>
|
||||
<div class="border border-slate-900 bg-slate-900 px-4 py-3 text-xl font-semibold text-white">
|
||||
{{ encyclopediaStore.unlockPercent }}%
|
||||
</div>
|
||||
</div>
|
||||
<NProgress
|
||||
class="mt-5"
|
||||
type="line"
|
||||
:show-indicator="false"
|
||||
:percentage="encyclopediaStore.unlockPercent"
|
||||
color="{stops:['#0ea5e9','#f59e0b']}"
|
||||
:height="12"
|
||||
/>
|
||||
</template>
|
||||
<EncyclopediaProgressCard
|
||||
v-if="isOwnProfile"
|
||||
:unlocked-count="encyclopediaStore.unlockedCount"
|
||||
:total-count="encyclopediaStore.cloudTypes.length || 10"
|
||||
:percent="encyclopediaStore.unlockPercent"
|
||||
:is-logged-in="true"
|
||||
/>
|
||||
|
||||
<template v-else>
|
||||
<p class="text-sm text-slate-500">公开贡献</p>
|
||||
<p class="mt-3 text-3xl font-bold text-slate-900">{{ approvedShots }}</p>
|
||||
<p class="mt-2 text-sm text-slate-500">当前公开可见的云图数量</p>
|
||||
</template>
|
||||
<NCard v-else class="border border-white/80 bg-white/85 shadow-sm backdrop-blur" :bordered="false">
|
||||
<p class="text-sm text-slate-500">公开贡献</p>
|
||||
<p class="mt-3 text-3xl font-bold text-slate-900">{{ approvedShots }}</p>
|
||||
<p class="mt-2 text-sm text-slate-500">当前公开可见的云图数量</p>
|
||||
</NCard>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user