43 lines
1.3 KiB
Vue
43 lines
1.3 KiB
Vue
<script setup lang="ts">
|
|
import type { WebNovel } from '~/types'
|
|
|
|
defineProps<{
|
|
novel: WebNovel
|
|
}>()
|
|
|
|
const router = useRouter()
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="cursor-pointer group"
|
|
@click="router.push(`/novels/${novel.id}`)"
|
|
>
|
|
<div class="relative overflow-hidden rounded-lg">
|
|
<img
|
|
:src="novel.cover"
|
|
:alt="novel.title"
|
|
class="w-full aspect-[3/4] object-cover group-hover:scale-105 transition-transform duration-300"
|
|
>
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent flex flex-col justify-end p-3">
|
|
<h3 class="font-bold text-white line-clamp-2">
|
|
{{ novel.title }}
|
|
</h3>
|
|
<p class="text-sm text-gray-200">
|
|
{{ typeof novel.author === 'string' ? novel.author : novel.author?.name }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="mt-2 space-y-1">
|
|
<div class="flex items-center gap-1">
|
|
<UIcon name="i-lucide-star" class="size-4 text-yellow-500" />
|
|
<span class="text-sm font-semibold">{{ (novel.rating || 0).toFixed(1) }}</span>
|
|
<span class="text-xs text-gray-500">· {{ novel.status }}</span>
|
|
</div>
|
|
<p class="text-xs text-gray-600 dark:text-gray-400">
|
|
{{ novel.chapters || 0 }} chapters
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|