小说网站前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

183 lines
4.5 KiB

<template>
<div class="book-card" @click="goToDetail">
<div class="book-cover">
<img :src="book.image" :alt="book.title">
<!-- 原创标签 -->
<div v-if="book.isOriginal == 'Y'" class="tag original">原创</div>
</div>
<div class="book-info">
<h3 class="book-title">{{ book.name }}</h3>
<p class="book-author">作者:{{ book.author }}</p>
<p class="book-intro" v-if="book.details">{{ book.details }}</p>
<div class="book-status">
<span class="status-tag" :class="statusClass">{{ statusText }}</span>
<span class="reading-count">{{ book.service }}</span>
</div>
</div>
</div>
</template>
<script>
import { computed } from 'vue';
import { useRouter } from 'vue-router';
export default {
name: 'BookCard',
props: {
book: {
type: Object,
required: true,
default: () => ({
id: '',
title: '',
author: '',
description: '',
cover: '',
status: '',
readCount: 0
})
}
},
setup(props) {
const router = useRouter();
const goToDetail = () => {
router.push({
path: `/book/${props.book.id}`
});
};
// 状态文本映射
const statusText = computed(() => {
const status = props.book.status;
if (status === 1 || status === '1' || status === 'completed') {
return '已完结';
}
return '连载中';
});
// 状态样式类映射
const statusClass = computed(() => {
const status = props.book.status;
if (status === 1 || status === '1' || status === 'completed') {
return 'completed';
}
return 'serializing';
});
return {
goToDetail,
statusText,
statusClass
};
}
};
</script>
<style lang="scss" scoped>
@use '@/assets/styles/variables.scss' as vars;
.book-card {
display: flex;
border-radius: 4px;
overflow: hidden;
transition: all 0.3s;
cursor: pointer;
background-color: #fff;
margin-bottom: 15px;
.book-cover {
width: 100px;
min-width: 100px;
height: 140px;
overflow: hidden;
position: relative;
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 4px;
}
.tag {
position: absolute;
top: 0;
left: 0;
font-size: 12px;
color: #fff;
padding: 2px 8px;
border-radius: 0 0 4px 0;
&.original {
background-color: #ffa502;
}
}
}
.book-info {
flex: 1;
padding: 12px;
display: flex;
flex-direction: column;
justify-content: space-between;
.book-title {
margin: 0 0 6px;
font-size: 16px;
font-weight: bold;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.book-author {
font-size: 14px;
color: #666;
margin: 0 0 8px;
}
.book-intro {
font-size: 12px;
color: #999;
line-height: 1.5;
margin: 0 0 auto;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.book-status {
margin-top: 8px;
display: flex;
align-items: center;
gap: 10px;
.status-tag {
padding: 2px 8px;
border-radius: 10px;
font-size: 12px;
&.serializing {
background-color: #67C23A33;
color: #67C23A;
}
&.completed {
background-color: #409EFF33;
color: #409EFF;
}
}
.reading-count {
font-size: 12px;
color: #999;
}
}
}
}
</style>