## 概述 本分支对前端进行了大规模适配与升级,核心是对齐新版后端 API 接口,并接入邮箱验证与密码找回流程。 ## 主要变更 - **API 适配**:对齐新版后端接口契约,重构 api 客户端与类型定义,移除前端臆造字段 - **认证流程**:接入邮箱验证(确认 / 重发确认)、密码找回(忘记密码 / 重置密码)全流程 - **管理后台**:前端对齐更新后的 API 契约 - **云图鉴**:展示云类型图标图片 - **UI 优化**:图片预览改为直角样式并调整关闭按钮 ## 影响范围 - API 层:src/lib/api.ts、src/types/api.ts、src/types/database.ts - 认证视图:src/views/auth/* - 管理后台:src/views/admin/AdminView.vue - 图鉴视图:src/views/encyclopedia/* - 状态管理:src/stores/* Reviewed-on: #9
93 lines
4.0 KiB
Vue
93 lines
4.0 KiB
Vue
<script setup lang="ts">
|
||
import { onMounted } from 'vue'
|
||
import { NEmpty, NSkeleton } from 'naive-ui'
|
||
import { useRouter } from 'vue-router'
|
||
import { imageUrl } from '@/lib/api'
|
||
import { useEncyclopediaStore } from '@/stores/encyclopedia'
|
||
|
||
const router = useRouter()
|
||
const encyclopediaStore = useEncyclopediaStore()
|
||
|
||
function typeImageUrl(iconId: string | null) {
|
||
return iconId ? imageUrl(iconId, 'preview') : ''
|
||
}
|
||
|
||
onMounted(() => encyclopediaStore.fetchCloudTypes())
|
||
</script>
|
||
|
||
<template>
|
||
<div class="relative">
|
||
<div class="oc-page-hero">
|
||
<div class="oc-container oc-container--content oc-page-hero__inner">
|
||
<p class="oc-page-eyebrow">Cloud Encyclopedia</p>
|
||
<h1 class="oc-page-title">云朵百科</h1>
|
||
<p class="oc-page-description">
|
||
浏览后端提供的云类型资料,了解云属名称、识别说明和社区公开观测记录。
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="oc-container oc-container--content oc-page-content">
|
||
<div v-if="encyclopediaStore.loadingCloudTypes" class="grid gap-5 md:grid-cols-2 lg:grid-cols-3">
|
||
<div v-for="n in 6" :key="n" class="oc-panel-card overflow-hidden border border-slate-200 bg-white">
|
||
<NSkeleton class="h-80 w-full" />
|
||
</div>
|
||
</div>
|
||
|
||
<div v-else-if="encyclopediaStore.cloudTypes.length" class="grid gap-5 md:grid-cols-2 lg:grid-cols-3">
|
||
<button
|
||
v-for="cloudType in encyclopediaStore.cloudTypes"
|
||
:key="cloudType.id"
|
||
type="button"
|
||
class="oc-interactive-card oc-panel-card relative isolate min-h-80 overflow-hidden border border-slate-200 bg-sky-50 text-left"
|
||
@click="router.push(`/encyclopedia/${cloudType.id}`)"
|
||
>
|
||
<img
|
||
v-if="cloudType.icon_id"
|
||
:src="typeImageUrl(cloudType.icon_id)"
|
||
:alt="`${cloudType.name}介绍图`"
|
||
class="absolute inset-0 -z-20 h-full w-full object-cover"
|
||
/>
|
||
<div
|
||
v-if="cloudType.icon_id"
|
||
class="absolute inset-0 -z-10 bg-gradient-to-t from-slate-950/90 via-slate-950/55 to-slate-950/25"
|
||
></div>
|
||
<div v-else class="absolute inset-0 -z-10 flex items-center justify-center text-sm font-medium text-slate-500">无图片</div>
|
||
|
||
<div class="flex min-h-80 flex-col p-5">
|
||
<div class="flex items-start justify-between gap-4">
|
||
<div>
|
||
<p class="oc-section-label" :class="cloudType.icon_id ? 'text-white/70' : 'text-slate-500'">Cloud Genus</p>
|
||
<h2 class="mt-2 text-xl font-bold" :class="cloudType.icon_id ? 'text-white' : 'text-slate-900'">{{ cloudType.name }}</h2>
|
||
<p
|
||
class="mt-1 font-mono text-xs uppercase tracking-[0.12em]"
|
||
:class="cloudType.icon_id ? 'text-white/75' : 'text-slate-500'"
|
||
>
|
||
{{ cloudType.genus || '未提供云属名称' }}
|
||
</p>
|
||
</div>
|
||
<span
|
||
class="shrink-0 border px-2.5 py-1 text-xs font-medium"
|
||
:class="cloudType.icon_id ? 'border-white/35 bg-slate-950/25 text-white backdrop-blur' : 'border-slate-200 bg-white text-slate-600'"
|
||
>
|
||
稀有度 {{ cloudType.rarity_value }}
|
||
</span>
|
||
</div>
|
||
<p class="mt-auto line-clamp-3 pt-16 text-sm leading-6" :class="cloudType.icon_id ? 'text-white/85' : 'text-slate-600'">
|
||
{{ cloudType.description || '暂未提供识别说明。' }}
|
||
</p>
|
||
<p
|
||
class="mt-4 border-t pt-4 text-xs font-semibold"
|
||
:class="cloudType.icon_id ? 'border-white/25 text-white' : 'border-slate-200 text-sky-700'"
|
||
>查看类型资料与公开云图 →</p>
|
||
</div>
|
||
</button>
|
||
</div>
|
||
|
||
<div v-else class="oc-empty-card border border-dashed border-slate-300 bg-white px-6 py-12">
|
||
<NEmpty description="暂时还没有云类型资料" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|