import { computed, ref } from 'vue' import { defineStore } from 'pinia' import { apiRequest } from '@/lib/api' import { useAuthStore } from '@/stores/auth' import type { ApiCollection } from '@/types/api' import type { CloudType, UserCollection } from '@/types/database' export interface CollectionPreviewCloud { id: string image_url: string thumbnail_url: string | null captured_at: string | null created_at: string location_name: string | null } export interface CollectionEntry extends UserCollection { firstCloud: CollectionPreviewCloud | null } function getErrorMessage(error: unknown) { return error instanceof Error ? error.message : '图鉴收藏加载失败' } export const useEncyclopediaStore = defineStore('encyclopedia', () => { const authStore = useAuthStore() const cloudTypes = ref([]) const myCollection = ref([]) const loadingCloudTypes = ref(false) const loadingCollection = ref(false) const cloudTypesLoaded = ref(false) const collectionLoadedForUserId = ref(null) const collectionError = ref('') const collectionMap = computed(() => new Map(myCollection.value.map(item => [item.cloud_type_id, item]))) const unlockedCount = computed(() => myCollection.value.length) const unlockProgress = computed(() => `${unlockedCount.value}/${cloudTypes.value.length || 10}`) const unlockPercent = computed(() => cloudTypes.value.length ? Math.round(unlockedCount.value / cloudTypes.value.length * 100) : 0) async function fetchCloudTypes(force = false) { if (cloudTypesLoaded.value && !force) return loadingCloudTypes.value = true try { cloudTypes.value = await apiRequest('/cloud-types', { auth: false }) cloudTypesLoaded.value = true } finally { loadingCloudTypes.value = false } } async function fetchMyCollection(force = false) { const userId = authStore.user?.id ?? null if (!userId) { myCollection.value = [] collectionLoadedForUserId.value = null collectionError.value = '' return } if (!force && collectionLoadedForUserId.value === userId) return loadingCollection.value = true collectionError.value = '' try { const rows = await apiRequest('/collections/me') myCollection.value = rows.map(({ first_cloud, cloud_type: _cloudType, ...collection }) => ({ ...collection, firstCloud: first_cloud, })) collectionLoadedForUserId.value = userId } catch (error) { myCollection.value = [] collectionLoadedForUserId.value = userId collectionError.value = getErrorMessage(error) } finally { loadingCollection.value = false } } function isUnlocked(cloudTypeId: number) { return collectionMap.value.has(cloudTypeId) } function getCollectionEntry(cloudTypeId: number) { return collectionMap.value.get(cloudTypeId) ?? null } return { cloudTypes, myCollection, loadingCloudTypes, loadingCollection, collectionError, unlockedCount, unlockProgress, unlockPercent, fetchCloudTypes, fetchMyCollection, isUnlocked, getCollectionEntry, } })