|
@@ -0,0 +1,250 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="top-nav">
|
|
|
|
+ <div
|
|
|
|
+ class="top-nav-container"
|
|
|
|
+ :class="{ simple: hideBgColor }"
|
|
|
|
+ :style="{ backgroundColor: bgColor }"
|
|
|
|
+ >
|
|
|
|
+ <div>
|
|
|
|
+ <div class="top-nav-lf">
|
|
|
|
+ <router-link v-if="showLogo" :to="{ name: 'home' }">
|
|
|
|
+ <img
|
|
|
|
+ class="top-nav__logo"
|
|
|
|
+ draggable="false"
|
|
|
|
+ src="@/assets/images/logo_02-min.png"
|
|
|
|
+ />
|
|
|
|
+ </router-link>
|
|
|
|
+
|
|
|
|
+ <div v-if="isDetail" class="top-nav-detail">
|
|
|
|
+ <router-link :to="{ name: 'home' }">
|
|
|
|
+ <img
|
|
|
|
+ :src="isDark ? LogoWhiteIcon : LogoIcon"
|
|
|
|
+ draggable="false"
|
|
|
|
+ style="display: block"
|
|
|
|
+ />
|
|
|
|
+ </router-link>
|
|
|
|
+ <div class="top-nav-detail__inner">
|
|
|
|
+ <div class="top-nav-detail__title">
|
|
|
|
+ <h1 class="limit-line">
|
|
|
|
+ {{ detail?.name }}
|
|
|
|
+ </h1>
|
|
|
|
+ <span @click="introductionVisible = true">查看简介</span>
|
|
|
|
+ </div>
|
|
|
|
+ <p>{{ detail?.author }} {{ detail?.press }} 编</p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="top-nav-rg">
|
|
|
|
+ <ul class="top-nav-rg-first">
|
|
|
|
+ <li @click="mobileVisible = true">手机版</li>
|
|
|
|
+ <li v-if="!isDetail">
|
|
|
|
+ <router-link :to="{ name: 'stack' }">书库</router-link>
|
|
|
|
+ </li>
|
|
|
|
+ <li
|
|
|
|
+ v-else
|
|
|
|
+ v-loading="joinLoading"
|
|
|
|
+ element-loading-custom-class="top-nav__loading"
|
|
|
|
+ @click="handleLike"
|
|
|
|
+ >
|
|
|
|
+ {{ detail?.isCollect === 1 ? "我的书架" : "加入书架" }}
|
|
|
|
+ </li>
|
|
|
|
+ </ul>
|
|
|
|
+
|
|
|
|
+ <div class="top-nav-rg__divider" />
|
|
|
|
+
|
|
|
|
+ <template v-if="isDetail">
|
|
|
|
+ <div class="top-nav-detail-nav">
|
|
|
|
+ <div
|
|
|
|
+ v-for="item in DETAIL_NAV"
|
|
|
|
+ :key="item.key"
|
|
|
|
+ class="top-nav-detail-nav__item"
|
|
|
|
+ :class="{ active: $route.params.type === item.key }"
|
|
|
|
+ @click="
|
|
|
|
+ $router.push({
|
|
|
|
+ name: 'detail',
|
|
|
|
+ params: {
|
|
|
|
+ id: route.params.id,
|
|
|
|
+ type: item.key,
|
|
|
|
+ },
|
|
|
|
+ })
|
|
|
|
+ "
|
|
|
|
+ >
|
|
|
|
+ <img
|
|
|
|
+ :src="
|
|
|
|
+ $route.params.type === item.key
|
|
|
|
+ ? item.activeIcon
|
|
|
|
+ : item.icon
|
|
|
|
+ "
|
|
|
|
+ />
|
|
|
|
+ <p>{{ item.text }}</p>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 简/繁体 -->
|
|
|
|
+ <img
|
|
|
|
+ v-show="$route.params.type === 'reader'"
|
|
|
|
+ :src="isSimplified ? jtIcon : ftIcon"
|
|
|
|
+ @click="epubStore.toggleText"
|
|
|
|
+ />
|
|
|
|
+
|
|
|
|
+ <!-- 书库 -->
|
|
|
|
+ <router-link :to="{ name: 'stack' }">
|
|
|
|
+ <img :src="isDark ? skDarkIcon : skIcon" />
|
|
|
|
+ </router-link>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="top-nav-rg__divider" />
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <el-popover
|
|
|
|
+ v-if="isLogin"
|
|
|
|
+ :width="124"
|
|
|
|
+ popper-class="top-nav-user-popover"
|
|
|
|
+ effect="dark"
|
|
|
|
+ trigger="click"
|
|
|
|
+ placement="bottom-end"
|
|
|
|
+ >
|
|
|
|
+ <template #reference>
|
|
|
|
+ <div class="top-nav-user">
|
|
|
|
+ <el-avatar :src="getFixUrl(userInfo.avatarUrl)" :size="30" />
|
|
|
|
+ <p>{{ userInfo.nickName }}</p>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <ul class="top-nav-user-toolbar">
|
|
|
|
+ <li @click="$router.push({ name: 'bookshelf' })">我的书架</li>
|
|
|
|
+ <li @click="baseStore.logout">退出登录</li>
|
|
|
|
+ </ul>
|
|
|
|
+ </el-popover>
|
|
|
|
+
|
|
|
|
+ <div v-else class="top-nav__login" @click="handleLogin">微信登录</div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <login-dialog v-model:visible="loginVisible" />
|
|
|
|
+ <mobile-dialog v-model:visible="mobileVisible" />
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup>
|
|
|
|
+import { watch, ref } from "vue";
|
|
|
|
+import { useRoute, useRouter } from "vue-router";
|
|
|
|
+import { useDark } from "@vueuse/core";
|
|
|
|
+import { storeToRefs } from "pinia";
|
|
|
|
+import { getFixUrl } from "@/utils";
|
|
|
|
+import { updateBookCollectApi } from "@/api";
|
|
|
|
+import { useBaseStore, useEpubStore, useDetailStore } from "@/stores";
|
|
|
|
+import LoginDialog from "../TopNav/components/LoginDialog.vue";
|
|
|
|
+import MobileDialog from "../TopNav/components/MobileDialog.vue";
|
|
|
|
+
|
|
|
|
+import LogoIcon from "@/assets/images/logo_03-min.png";
|
|
|
|
+import LogoWhiteIcon from "@/assets/images/logo-min.png";
|
|
|
|
+import TextIcon from "./images/icon_text-min.png";
|
|
|
|
+import TextActiveIcon from "./images/icon_text_active-min.png";
|
|
|
|
+import VideoIcon from "./images/icon_video-min.png";
|
|
|
|
+import VideoActiveIcon from "./images/icon_video_active-min.png";
|
|
|
|
+import ImgIcon from "./images/icon_img-min.png";
|
|
|
|
+import ImgActiveIcon from "./images/icon_img_active-min.png";
|
|
|
|
+import jtIcon from "./images/icon_font-min.png";
|
|
|
|
+import ftIcon from "./images/icon_font_active-min.png";
|
|
|
|
+import skIcon from "./images/icon_book-min.png";
|
|
|
|
+import skDarkIcon from "./images/icon_book_dark-min.png";
|
|
|
|
+
|
|
|
|
+const DETAIL_NAV = [
|
|
|
|
+ {
|
|
|
|
+ key: "reader",
|
|
|
|
+ icon: TextIcon,
|
|
|
|
+ activeIcon: TextActiveIcon,
|
|
|
|
+ text: "文本",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ key: "video",
|
|
|
|
+ icon: VideoIcon,
|
|
|
|
+ activeIcon: VideoActiveIcon,
|
|
|
|
+ text: "视频",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ key: "photocopy",
|
|
|
|
+ icon: ImgIcon,
|
|
|
|
+ activeIcon: ImgActiveIcon,
|
|
|
|
+ text: "影印",
|
|
|
|
+ },
|
|
|
|
+];
|
|
|
|
+
|
|
|
|
+const route = useRoute();
|
|
|
|
+const router = useRouter();
|
|
|
|
+const isDark = useDark();
|
|
|
|
+
|
|
|
|
+const detailStore = useDetailStore();
|
|
|
|
+const { introductionVisible, detail } = storeToRefs(detailStore);
|
|
|
|
+const baseStore = useBaseStore();
|
|
|
|
+const { isLogin, loginVisible, userInfo } = storeToRefs(baseStore);
|
|
|
|
+const epubStore = useEpubStore(window.pinia);
|
|
|
|
+const { isSimplified } = storeToRefs(epubStore);
|
|
|
|
+
|
|
|
|
+const isDetail = ref(false);
|
|
|
|
+const showLogo = ref(false);
|
|
|
|
+const hideBgColor = ref(false);
|
|
|
|
+const bgColor = ref("");
|
|
|
|
+const joinLoading = ref(false);
|
|
|
|
+const mobileVisible = ref(false);
|
|
|
|
+
|
|
|
|
+// 加入书架
|
|
|
|
+const handleLike = async () => {
|
|
|
|
+ if (!baseStore.loginValidator()) return;
|
|
|
|
+
|
|
|
|
+ if (detail.value.isCollect !== 1) {
|
|
|
|
+ try {
|
|
|
|
+ joinLoading.value = true;
|
|
|
|
+ await updateBookCollectApi(detail.value.id, {
|
|
|
|
+ status: 1,
|
|
|
|
+ });
|
|
|
|
+ detail.value.isCollect = 1;
|
|
|
|
+ } finally {
|
|
|
|
+ joinLoading.value = false;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ router.push({ name: "bookshelf" });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const handleLogin = async () => {
|
|
|
|
+ loginVisible.value = true;
|
|
|
|
+ // const data = await fakeLoginApi(1);
|
|
|
|
+ // baseStore.login(data);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+watch(route, (v) => {
|
|
|
|
+ isDetail.value = v.name === "detail";
|
|
|
|
+ showLogo.value = v.meta.showLogo ?? false;
|
|
|
|
+ hideBgColor.value =
|
|
|
|
+ (v.meta.hideTopNavBgColor || Boolean(v.meta.topNavBgColor)) ?? true;
|
|
|
|
+ bgColor.value = v.meta.topNavBgColor ?? "";
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+// 目前没有公众号,先默认登录
|
|
|
|
+// onMounted(() => {
|
|
|
|
+// handleLogin();
|
|
|
|
+// });
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
+@import "./index.scss";
|
|
|
|
+</style>
|
|
|
|
+
|
|
|
|
+<style lang="scss">
|
|
|
|
+.el-popover.top-nav-user-popover {
|
|
|
|
+ --el-popover-padding: 10px;
|
|
|
|
+ min-width: 124px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.top-nav__loading {
|
|
|
|
+ --el-loading-spinner-size: 20px;
|
|
|
|
+
|
|
|
|
+ top: -5px;
|
|
|
|
+ left: -10px;
|
|
|
|
+ right: -10px;
|
|
|
|
+ bottom: -5px;
|
|
|
|
+}
|
|
|
|
+</style>
|