更新:增加“图书首页”功能
This commit is contained in:
178
components/book/BookCardIndex.vue
Normal file
178
components/book/BookCardIndex.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user