179 lines
3.4 KiB
Vue
179 lines
3.4 KiB
Vue
<template>
|
|
<view
|
|
:class="['book-card', `book-card-${layout}`]"
|
|
@click="handleClick"
|
|
>
|
|
<image
|
|
:src="book.images"
|
|
:class="['book-cover', `book-cover-${layout}`]"
|
|
mode="aspectFill"
|
|
/>
|
|
<view :class="['book-info', `book-info-${layout}`]">
|
|
<text :class="['book-title', `book-title-${layout}`]">{{ book.name }}</text>
|
|
<view v-if="layout === 'vertical'" class="book-footer">
|
|
<text v-if="displayPrice" class="book-price">{{ displayPrice }}</text>
|
|
<text v-if="displayStats" class="book-stats">{{ displayStats }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
import type { IBookWithStats, IVipInfo } from '@/types/home'
|
|
|
|
interface Props {
|
|
book: IBookWithStats
|
|
layout?: 'horizontal' | 'vertical'
|
|
showPrice?: boolean
|
|
showStats?: boolean
|
|
vipInfo?: IVipInfo | null
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
layout: 'vertical',
|
|
showPrice: true,
|
|
showStats: true,
|
|
vipInfo: null
|
|
})
|
|
|
|
const emit = defineEmits<{
|
|
click: [bookId: number]
|
|
}>()
|
|
|
|
const { t } = useI18n()
|
|
|
|
/**
|
|
* 计算显示的价格
|
|
*/
|
|
const displayPrice = computed(() => {
|
|
if (!props.showPrice) return ''
|
|
|
|
// 已购买不显示价格
|
|
if (props.book.isBuy) return ''
|
|
|
|
// VIP用户且图书为VIP专享
|
|
if (props.vipInfo?.id && props.book.isVip === '2') {
|
|
const price = props.book.sysDictData?.dictValue
|
|
return price ? `$ ${price} NZD` : ''
|
|
}
|
|
|
|
// 普通用户
|
|
if (!props.vipInfo?.id) {
|
|
const price = props.book.sysDictData?.dictValue
|
|
return price ? `$ ${price} NZD` : ''
|
|
}
|
|
|
|
return ''
|
|
})
|
|
|
|
/**
|
|
* 计算显示的统计信息
|
|
*/
|
|
const displayStats = computed(() => {
|
|
if (!props.showStats) return ''
|
|
|
|
if (props.book.readCount && props.book.readCount > 0) {
|
|
return `${props.book.readCount}${t('bookHome.readingCount')}`
|
|
}
|
|
|
|
if (props.book.buyCount && props.book.buyCount > 0) {
|
|
return `${props.book.buyCount}${t('bookHome.purchased')}`
|
|
}
|
|
|
|
return ''
|
|
})
|
|
|
|
/**
|
|
* 处理点击事件
|
|
*/
|
|
const handleClick = () => {
|
|
emit('click', props.book.bookId || props.book.id)
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.book-card {
|
|
cursor: pointer;
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
// 横向布局
|
|
.book-card-horizontal {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-right: 25rpx;
|
|
|
|
.book-cover-horizontal {
|
|
width: 110rpx;
|
|
height: 135rpx;
|
|
border-radius: 10rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.book-info-horizontal {
|
|
flex: 1;
|
|
margin-left: 15rpx;
|
|
}
|
|
|
|
.book-title-horizontal {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 32rpx;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
}
|
|
|
|
// 纵向布局
|
|
.book-card-vertical {
|
|
display: flex;
|
|
flex-direction: column;
|
|
text-align: center;
|
|
|
|
.book-cover-vertical {
|
|
width: 160rpx;
|
|
height: 200rpx;
|
|
border-radius: 10rpx;
|
|
}
|
|
|
|
.book-info-vertical {
|
|
width: 160rpx;
|
|
margin-top: 10rpx;
|
|
}
|
|
|
|
.book-title-vertical {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 40rpx;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.book-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-top: 5rpx;
|
|
|
|
.book-price {
|
|
font-size: 28rpx;
|
|
color: #ff4703;
|
|
}
|
|
|
|
.book-stats {
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
</style>
|