- <template>
- <div class="book-detail-container">
- <!-- 小说基本信息部分 -->
- <div class="book-info-wrapper">
- <div class="book-info">
- <div class="book-cover">
- <img :src="book.cover" :alt="book.title">
- </div>
- <div class="book-details">
- <h1 class="book-title">{{ book.title }}</h1>
- <div class="book-meta">
- <div class="meta-item">
- <span class="label">作者:</span>
- <span class="value">{{ book.author }}</span>
- </div>
- <div class="meta-item book-status-row">
- <span class="status-badge">{{ book.status }}</span>
- <span class="dot">·</span>
- <span class="reading-tip">大家都在读</span>
- </div>
- </div>
- <div class="book-user-info">
- <div class="user-badges">
- <img class="level-icon" src="@/assets/images/book/level.png" alt="我的等级" />
- <span class="badge-label">我的等级</span>
- </div>
- <div class="user-medal">
- <img class="medal-icon" src="@/assets/images/image-1.png" alt="勋章" />
- </div>
- <div class="user-avatar-block">
- <img class="user-avatar" src="@/assets/images/center/headImage.png" alt="用户头像" />
- <span class="user-name">小巴</span>
- <span class="dot">·</span>
- <span class="user-title">VIP会员</span>
- </div>
- <span class="user-intimacy">1000 累计亲密值</span>
- </div>
-
- <div class="action-buttons">
- <div class="action-btn-group">
- <el-button class="reward-btn" plain @click="showRewardDialog">互动打赏</el-button>
- </div>
- <div class="action-btn-group">
- <el-button
- :class="['add-to-shelf-btn', isInShelf ? 'in-shelf' : '']"
- :type="isInShelf ? '' : 'primary'"
- @click="toggleShelf"
- >{{ isInShelf ? '已加入书架' : '加入书架' }}</el-button>
- </div>
- <div class="action-btn-group">
- <el-button class="read-btn"
- @click="goToChapter(1)"
- style="background:#0A2463;color:#fff;border:none;">点击阅读</el-button>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 主体内容区域:左右分栏 -->
- <div class="book-main-content">
- <div class="main-left">
- <!-- 推荐票/亲密值统计 -->
- <BookStats :book-id="book.id" />
- <!-- 小说介绍 -->
- <BookIntro :book-data="book" />
- <!-- 目录 -->
- <BookCatalog :book-id="book.id" />
- <!-- 评论 -->
- <BookComments :book-id="book.id" />
- </div>
- <div class="main-right">
- <!-- 读者亲密值榜单 -->
- <IntimacyRanking :book-id="book.id" />
- </div>
- </div>
- </div>
- <!-- 互动打赏弹窗 -->
- <InteractiveReward
- v-model:visible="rewardDialogVisible"
- :book-id="book.id"
- @reward-success="handleRewardSuccess"
- />
- </template>
-
- <script>
- import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
- import { useRoute, useRouter } from 'vue-router';
- import BookCard from '@/components/common/BookCard.vue';
- import BookStats from '@/components/book/BookStats.vue';
- import BookIntro from '@/components/book/BookIntro.vue';
- import BookCatalog from '@/components/book/BookCatalog.vue';
- import BookComments from '@/components/book/BookComments.vue';
- import IntimacyRanking from '@/components/ranking/IntimacyRanking.vue';
- import InteractiveReward from '@/components/book/InteractiveReward.vue';
-
- export default {
- name: 'BookDetail',
- components: {
- BookCard,
- BookStats,
- BookIntro,
- BookCatalog,
- BookComments,
- IntimacyRanking,
- InteractiveReward
- },
- setup() {
- const route = useRoute();
- const router = useRouter();
- const bookId = route.params.id;
-
- const book = reactive({
- id: bookId,
- title: '重生之财源滚滚',
- author: '老鹰的沙',
- category: '都市小说',
- status: '已完结',
- userGroup: '638781087(网友交流群)',
- cover: 'https://bookcover.yuewen.com/qdbimg/349573/1041637443/150.webp',
- description: `<p>当那一世——</p>
- <p>贺季宁曾经是A市土豪公司的金牌经理,工资高福利好,女友漂亮车位靓,最重要的是老板信任他。但是贺季宁的对手不服,老板娘不喜欢他,不怀好意的对手们联合一起,终于把他拉下台了,他失去工作,更可悲的是,他连公司配他的贷款的房子都搭进去了,欠了几百万的债,女友也离他而去。</p>
- <p>临终前,他喃喃自语:如果老天给我重来一次的机会,我一定要好好做人,赚很多钱,让那帮人看着我过得好就比他们难受!</p>`,
- userGroup: '638781087(网友交流群)',
- chapters: [
- { id: '1', title: '第一章 重回2004', isNew: false },
- { id: '2', title: '第二章 旧车旧房', isNew: false },
- { id: '3', title: '第三章 再拼一把', isNew: false },
- { id: '4', title: '第四章 带女朋友逛街', isNew: false },
- { id: '5', title: '第五章 小刺激', isNew: false },
- { id: '6', title: '第六章 老王的门道', isNew: false },
- { id: '7', title: '第七章 正中家门', isNew: false },
- { id: '8', title: '第八章 被逼迫的交易', isNew: false },
- { id: '9', title: '第九章 意外惊喜', isNew: false },
- { id: '10', title: '第十章 生意的桥梁', isNew: true },
- { id: '11', title: '第十一章 家族分崩离析', isNew: false },
- { id: '12', title: '第十二章 老张没来', isNew: false }
- ],
- comments: [
- {
- username: '万年捧',
- avatar: 'https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKlR5PibUEEsVjXGfH4c1eR5hXDicoH0EJUTHYwDO3EvZLXXgON8GrNTbRg8DnzaddicibYnGcfq28tYg/132',
- time: '2022-07-03',
- content: '这是本年内看的唯一一部完结的!看的人真幸运,发家文和风险防控写的都是一流'
- },
- {
- username: '残生往事',
- avatar: 'https://thirdwx.qlogo.cn/mmopen/vi_32/3F4feeHnMyoGjqKfP8vGKCHwyvovMHiaO0Q1QkQMRTGibLcyJbUcUJ4LmdkkDqC5ZcqP1rvqKMviaYAyehqYb6ciaA/132',
- content: '我很喜欢男主的性格,不小心眼,有格局,做事情多考虑下一步,商业和情感都处理得不错,就是那个林涵有点没必要吧?'
- }
- ]
- });
-
- // 推荐书籍
- const recommendedBooks = reactive([
- {
- id: '101',
- title: '三体',
- author: '刘慈欣',
- cover: 'https://picsum.photos/120/160?random=1',
- status: '已完结'
- },
- {
- id: '102',
- title: '活着',
- author: '余华',
- cover: 'https://picsum.photos/120/160?random=2',
- status: '已完结'
- },
- {
- id: '103',
- title: '平凡的世界',
- author: '路遥',
- cover: 'https://picsum.photos/120/160?random=3',
- status: '已完结'
- },
- {
- id: '104',
- title: '围城',
- author: '钱钟书',
- cover: 'https://picsum.photos/120/160?random=4',
- status: '已完结'
- }
- ]);
-
- const activeTab = ref('intro');
- const currentPage = ref(1);
- const commentText = ref('');
- const isInShelf = ref(false);
- const rewardDialogVisible = ref(false);
-
- const handlePageChange = (page) => {
- currentPage.value = page;
- // 实际应用中这里应该加载对应页的数据
- };
-
- // 创建一个清理函数
- const cleanup = () => {
- // 清理所有响应式数据
- Object.keys(book).forEach(key => {
- if (typeof book[key] === 'object') {
- book[key] = null;
- }
- });
- activeTab.value = 'intro';
- currentPage.value = 1;
- commentText.value = '';
- isInShelf.value = false;
- rewardDialogVisible.value = false;
- };
-
- // 在组件销毁前清理
- onBeforeUnmount(() => {
- cleanup();
- });
-
- // 修改路由导航方式
- const goToChapter = (chapterId) => {
- cleanup();
- router.push({
- name: 'ChapterDetail',
- params: {
- id: bookId,
- chapterId: chapterId
- }
- });
- };
-
- const submitComment = () => {
- if (!commentText.value.trim()) {
- ElMessage.warning('请输入评论内容');
- return;
- }
-
- // 实际应用中这里应该调用API提交评论
- book.comments.unshift({
- username: '当前用户',
- avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
- time: new Date().toLocaleString(),
- content: commentText.value
- });
-
- commentText.value = '';
- };
-
- const toggleShelf = () => {
- isInShelf.value = !isInShelf.value;
- };
-
- const showRewardDialog = () => {
- rewardDialogVisible.value = true;
- };
-
- const handleRewardSuccess = (items) => {
- console.log('打赏成功,打赏项目:', items);
- // 这里可以添加刷新亲密值或其他相关数据的逻辑
- };
-
- onMounted(() => {
- // 实际应用中这里应该根据bookId从API获取书籍详情
- console.log('加载书籍详情,ID:', bookId);
- });
-
- return {
- book,
- recommendedBooks,
- activeTab,
- currentPage,
- commentText,
- handlePageChange,
- goToChapter,
- submitComment,
- isInShelf,
- toggleShelf,
- rewardDialogVisible,
- showRewardDialog,
- handleRewardSuccess,
- cleanup
- };
- }
- };
- </script>
-
- <style lang="scss" scoped>
- @use '@/assets/styles/variables.scss' as vars;
-
- .book-detail-container {
- width: 100%;
- background-color: #f5f5f5;
- }
-
- // 小说基本信息部分
- .book-info-wrapper {
- background-color: #fff;
- padding: 30px 0;
- border-bottom: 1px solid #eee;
-
- .book-info {
- display: flex;
- max-width: 1200px;
- margin: 0 auto;
- padding: 0 20px;
-
- .book-cover {
- width: 165px;
- height: 220px;
- margin-right: 30px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
-
- img {
- width: 100%;
- height: 100%;
- object-fit: cover;
- border-radius: 6px;
- }
- }
-
- .book-details {
- flex: 1;
-
- .book-title {
- font-size: 24px;
- font-weight: bold;
- margin: 0 0 15px 0;
- color: #333;
- }
-
- .book-meta {
- margin-bottom: 8px;
- .book-status-row {
- display: flex;
- align-items: center;
- font-size: 15px;
- margin-top: 10px;
- .status-badge {
- background: #eaffea;
- color: #52c41a;
- border-radius: 6px;
- padding: 2px 12px;
- font-size: 15px;
- font-weight: 500;
- margin-right: 8px;
- }
- .dot {
- color: #d1d1d1;
- margin: 0 8px;
- font-size: 18px;
- }
- .reading-tip {
- color: #bdbdbd;
- font-size: 15px;
- }
- }
- }
- .book-user-info {
- display: flex;
- align-items: center;
- margin-bottom: 18px;
- .user-badges {
- display: flex;
- align-items: center;
- margin-right: 18px;
- .level-icon {
- width: 36px;
- height: 36px;
- }
- .badge-label {
- color: #b88a4a;
- font-size: 14px;
- margin-left: 4px;
- }
- }
- .user-medal {
- margin-right: 18px;
- .medal-icon {
- width: 44px;
- height: 44px;
- }
- }
- .user-avatar-block {
- display: flex;
- align-items: center;
- margin-right: 18px;
- .user-avatar {
- width: 36px;
- height: 36px;
- border-radius: 50%;
- margin-right: 8px;
- }
- .user-name {
- color: #222;
- font-size: 16px;
- font-weight: 500;
- margin-right: 4px;
- }
- .dot {
- color: #d1d1d1;
- margin: 0 8px;
- font-size: 18px;
- }
- .user-title {
- background: #ede6ff;
- color: #a97cff;
- border-radius: 8px;
- padding: 2px 10px;
- font-size: 15px;
- margin-left: 2px;
- }
- }
- .user-intimacy {
- color: #bdbdbd;
- font-size: 15px;
- }
- }
-
- .action-buttons {
- display: flex;
- gap: 24px;
- margin-top: 10px;
- .action-btn-group {
- display: flex;
- flex-direction: column;
- align-items: center;
- .el-button {
- width: 140px;
- height: 40px;
- font-size: 16px;
- border-radius: 4px;
- margin: 0;
- font-weight: 500;
- }
- .diamond-icon {
- width: 28px;
- height: 18px;
- margin-top: 4px;
- }
- .reward-btn {
- color: #0A2463;
- border: 1.5px solid #0A2463;
- background: #fff;
- }
- .add-to-shelf-btn {
- background: #FF7C6A;
- color: #fff;
- border: none;
- }
- .add-to-shelf-btn.in-shelf {
- background: #fff;
- color: #FF7C6A;
- border: 1.5px solid #FF7C6A;
- }
- .read-btn {
- background: #0A2463;
- color: #fff;
- border: none;
- }
- }
- }
- }
- }
- }
-
- .book-main-content {
- display: flex;
- gap: 3px;
- margin-top: 20px;
- .main-left {
- flex: 1.8;
- min-width: 0;
- display: flex;
- flex-direction: column;
- gap: 3px;
- }
- .main-right {
- flex: 1;
- min-width: 220px;
- max-width: 280px;
- }
- }
- </style>
|