Files
taimed-international-app/components/book/BookCardIndex.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('home.readingCount')}`
}
if (props.book.buyCount && props.book.buyCount > 0) {
return `${props.book.buyCount}${t('home.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>