|
|
@@ -0,0 +1,186 @@
|
|
|
+<template>
|
|
|
+ <router-link
|
|
|
+ :to="{ name: 'detail', params: { id: _item.id, type: 'reader' } }"
|
|
|
+ class="book-card"
|
|
|
+ :class="{ row: isRow, large: size === 'large' }"
|
|
|
+ >
|
|
|
+ <div class="book-card-img">
|
|
|
+ <el-image :src="`${baseUrl}${_item.thumb}`" fit="cover" />
|
|
|
+
|
|
|
+ <img
|
|
|
+ v-if="showLike"
|
|
|
+ class="book-card-img__like"
|
|
|
+ :src="isLike ? LikeIcon : UnLikeIcon"
|
|
|
+ draggable="false"
|
|
|
+ :title="isLike ? '移除书架' : '加入书架'"
|
|
|
+ @click.prevent="handleLike"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div v-if="showRead" class="book-card-img__tag">读过</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="book-card-inner">
|
|
|
+ <p class="book-card__name limit-line">{{ _item.name }}</p>
|
|
|
+ <p v-if="isRow" class="limit-line">{{ _item.author }}</p>
|
|
|
+ <p class="limit-line">{{ _item.press }}</p>
|
|
|
+ </div>
|
|
|
+ </router-link>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { computed } from "vue";
|
|
|
+import { getBaseUrl } from "@/utils";
|
|
|
+import { updateBookCollectApi } from "@/api";
|
|
|
+import LikeIcon from "@/assets/images/icon_like.png";
|
|
|
+import UnLikeIcon from "@/assets/images/icon_unlike.png";
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ // 模式 row-横版 column-竖版
|
|
|
+ type: {
|
|
|
+ type: String,
|
|
|
+ required: false,
|
|
|
+ default: "row",
|
|
|
+ },
|
|
|
+ // 尺寸 normal large
|
|
|
+ size: {
|
|
|
+ type: String,
|
|
|
+ required: false,
|
|
|
+ defualt: "normal",
|
|
|
+ },
|
|
|
+ showLike: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ showRead: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ item: {
|
|
|
+ type: Object,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+});
|
|
|
+const emits = defineEmits(["update:item"]);
|
|
|
+
|
|
|
+const baseUrl = getBaseUrl();
|
|
|
+const isRow = computed(() => props.type === "row");
|
|
|
+const isLike = computed(() => _item.value.isCollect === 1);
|
|
|
+
|
|
|
+const _item = computed({
|
|
|
+ get() {
|
|
|
+ return props.item;
|
|
|
+ },
|
|
|
+ set(v) {
|
|
|
+ emits("update:item", v);
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const handleLike = async () => {
|
|
|
+ const temp = isLike.value;
|
|
|
+ try {
|
|
|
+ _item.value.isCollect = temp ? 2 : 1;
|
|
|
+ await updateBookCollectApi(_item.value.id, {
|
|
|
+ status: temp ? 2 : 1,
|
|
|
+ });
|
|
|
+ } catch (err) {
|
|
|
+ _item.value.isCollect = temp;
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.book-card {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 150px;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ // 横版样式
|
|
|
+ &.row {
|
|
|
+ width: 100%;
|
|
|
+ flex-direction: row;
|
|
|
+ gap: 18px;
|
|
|
+ line-height: 16px;
|
|
|
+
|
|
|
+ &.large {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 18px;
|
|
|
+ line-height: 21px;
|
|
|
+
|
|
|
+ .book-card-img {
|
|
|
+ width: 114px;
|
|
|
+ height: 146px;
|
|
|
+ }
|
|
|
+ .book-card__name {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ font-size: 24px;
|
|
|
+ line-height: 34px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .book-card-img {
|
|
|
+ width: 90px;
|
|
|
+ height: 115px;
|
|
|
+ }
|
|
|
+ .book-card-inner {
|
|
|
+ flex: 1;
|
|
|
+ text-align: left;
|
|
|
+ }
|
|
|
+ .book-card__name {
|
|
|
+ margin-top: unset;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ line-height: 22px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.large {
|
|
|
+ width: 192px;
|
|
|
+
|
|
|
+ .book-card-img {
|
|
|
+ height: 259px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-img {
|
|
|
+ position: relative;
|
|
|
+ flex-shrink: 0;
|
|
|
+ width: inherit;
|
|
|
+ height: 200px;
|
|
|
+
|
|
|
+ .el-image {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ &__like {
|
|
|
+ position: absolute;
|
|
|
+ top: 4px;
|
|
|
+ right: 4px;
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ }
|
|
|
+ &__tag {
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ right: 10px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 43px;
|
|
|
+ height: 24px;
|
|
|
+ color: white;
|
|
|
+ font-size: 12px;
|
|
|
+ border-radius: 2px;
|
|
|
+ background: rgba(0, 0, 0, 0.3);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-inner {
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ &__name {
|
|
|
+ margin-top: 8px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-family: "Source Han Serif CN-Bold";
|
|
|
+ opacity: 1 !important;
|
|
|
+ }
|
|
|
+ p {
|
|
|
+ opacity: 0.8;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|