visuddhinanda 2 дней назад
Родитель
Сommit
bc5d814d27

+ 238 - 0
api-v12/resources/css/reader.css

@@ -0,0 +1,238 @@
+/* resources/css/reader.css */
+
+/* 基础样式 */
+body {
+    font-family: "Inter", sans-serif;
+    transition: background-color 0.3s, color 0.3s;
+}
+
+.main-container {
+    display: flex;
+    gap: 20px;
+    padding: 20px;
+    max-width: 1400px;
+    margin: 0 auto;
+}
+
+.toc-sidebar {
+    width: 250px;
+    flex-shrink: 0;
+    display: none;
+    position: sticky;
+    top: 0;
+    height: 100vh;
+    overflow-y: auto;
+    overflow-x: hidden;
+    scrollbar-width: thin;
+}
+
+.toc-sidebar .card-body {
+    height: 100%;
+    overflow-y: auto;
+    overflow-x: hidden;
+}
+
+.content-area {
+    flex-grow: 1;
+    max-width: 100%;
+}
+
+.right-sidebar {
+    width: 300px;
+    flex-shrink: 0;
+    display: none;
+}
+
+.related-books {
+    margin-top: 30px;
+}
+
+.card-img-container {
+    height: 150px;
+    overflow: hidden;
+}
+
+.card-img-container img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+/* 响应式布局 */
+@media (max-width: 767px) {
+    .content-area {
+        width: 100%;
+    }
+
+    .main-container {
+        padding: 0;
+    }
+
+    .card {
+        border: none;
+    }
+}
+
+@media (min-width: 768px) {
+    .toc-sidebar {
+        display: block;
+    }
+
+    .content-area {
+        max-width: calc(100% - 270px);
+    }
+}
+
+@media (min-width: 992px) {
+    .right-sidebar {
+        display: block;
+    }
+
+    .content-area {
+        max-width: calc(100% - 570px);
+    }
+}
+
+/* 暗色模式 */
+.dark-mode {
+    background-color: #1a1a1a;
+    color: #ffffff;
+}
+
+.dark-mode .card {
+    background-color: #2a2a2a;
+    border-color: #3a3a3a;
+    color: #ffffff;
+}
+
+.dark-mode .navbar {
+    background-color: #2a2a2a;
+}
+
+.dark-mode .offcanvas {
+    background-color: #2a2a2a;
+    color: #ffffff;
+}
+
+.dark-mode .offcanvas .nav-link {
+    color: #ffffff;
+}
+
+.dark-mode .toc-sidebar,
+.dark-mode .right-sidebar {
+    background-color: #2a2a2a;
+}
+
+/* 目录样式 */
+.toc-sidebar ul,
+.offcanvas-body ul {
+    list-style: none;
+    padding: 0;
+}
+
+.toc-sidebar ul li,
+.offcanvas-body ul li {
+    padding: 5px 0;
+}
+
+.toc-sidebar ul li a,
+.offcanvas-body ul li a {
+    color: #206bc4;
+    text-decoration: none;
+}
+
+.toc-sidebar ul li a:hover {
+    text-decoration: none;
+}
+
+.offcanvas-body ul li a:hover {
+    text-decoration: underline;
+}
+
+.dark-mode .toc-sidebar ul li a,
+.dark-mode .offcanvas-body ul li a {
+    color: #4dabf7;
+}
+
+.toc-level-1 {
+    padding-left: 0 !important;
+}
+
+.toc-level-2 {
+    padding-left: 16px !important;
+}
+
+.toc-level-3 {
+    padding-left: 24px !important;
+}
+
+.toc-level-4 {
+    padding-left: 36px !important;
+}
+
+.toc-disabled {
+    color: #6c757d;
+    cursor: not-allowed;
+    pointer-events: none;
+}
+
+.dark-mode .toc-disabled {
+    color: #adb5bd;
+}
+
+.toc_item {
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.toc_item:hover {
+    color: #206bc4 !important;
+    background: rgba(32, 107, 196, 0.15);
+    border-radius: 2px;
+    cursor: pointer;
+}
+
+.toc_item a,
+.toc_item span {
+    display: block;
+    width: 100%;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.toc-active {
+    color: #206bc4 !important;
+    font-weight: 600;
+    background: rgba(32, 107, 196, 0.08);
+    border-left: 3px solid #206bc4;
+    border-radius: 2px;
+    cursor: default;
+    pointer-events: none;
+}
+
+.dark-mode .toc-active {
+    color: #4dabf7 !important;
+    background: rgba(77, 171, 247, 0.1);
+    border-left-color: #4dabf7;
+}
+
+.origin {
+    color: darkred;
+}
+
+/* 术语引用样式 */
+.term-ref {
+    cursor: pointer;
+    text-decoration: underline dotted;
+    text-underline-offset: 4px;
+}
+
+.term_invalid {
+    color: red;
+}
+
+.term-ref:hover {
+    color: var(--tblr-primary);
+}

+ 83 - 0
api-v12/resources/js/term-tooltip.js

@@ -0,0 +1,83 @@
+/**
+ * <span
+    class="term-ref"
+    data-id="b45e7b10-2b75-4f5f-ac63-be686116043c"
+    data-term="anicca"
+>
+    无常
+</span>
+ */
+document.addEventListener("DOMContentLoaded", () => {
+    const cache = {};
+
+    const drawerEl = document.getElementById("termDrawer");
+
+    const drawer = new bootstrap.Offcanvas(drawerEl);
+
+    const drawerTitle = document.getElementById("termDrawerTitle");
+
+    const drawerBody = document.getElementById("termDrawerBody");
+
+    function isMobile() {
+        return window.innerWidth < 768;
+    }
+
+    async function fetchTerm(term) {
+        if (cache[term]) return cache[term];
+        console.info("term", term);
+        const res = await fetch(`/api/v2/terms/${term}`);
+
+        const data = await res.json();
+
+        cache[term] = data.data;
+
+        return data.data;
+    }
+
+    document.querySelectorAll(".term-ref").forEach((el) => {
+        let popover = null;
+
+        el.addEventListener("mouseenter", async () => {
+            console.info("mouseenter");
+            if (isMobile()) return;
+
+            if (popover) return;
+            const pali = el.dataset.term;
+            const data = await fetchTerm(el.dataset.id);
+
+            popover = new bootstrap.Popover(el, {
+                trigger: "manual",
+                html: true,
+                placement: "bottom",
+
+                content: `
+            <div style="max-width:300px">
+                <h4>${data.word}</h4>
+                <div>${data.summary}</div>
+            </div>
+        `,
+            });
+
+            popover.show();
+        });
+
+        el.addEventListener("mouseleave", () => {
+            if (popover) {
+                popover.dispose();
+                popover = null;
+            }
+        });
+
+        el.addEventListener("click", async () => {
+            if (!isMobile()) return;
+
+            const data = await fetchTerm(el.dataset.id);
+
+            drawerTitle.innerHTML = data.word;
+
+            drawerBody.innerHTML = data.summary;
+
+            drawer.show();
+        });
+    });
+});

+ 63 - 0
api-v12/resources/views/components/library/header.blade.php

@@ -0,0 +1,63 @@
+{{-- api-v12/resources/views/components/library/header.blade.php --}}
+<div class="anthology-breadcrumb-bar">
+    <div class="container-xl">
+        <div class="bc-inner">
+
+            <ol class="breadcrumb mb-0">
+                @yield('breadcrumb')
+            </ol>
+
+            <ul class="bc-nav">
+                <li><a href="{{ route('library.home') }}">首页</a></li>
+                <li><a href="{{ route('library.wiki.index') }}">百科</a></li>
+                <li><a href="{{ route('library.anthology.index') }}">文集</a></li>
+                <li><a href="{{ route('library.download') }}">下载</a></li>
+
+                @auth
+                <li><a href="#">我的账户</a></li>
+                @else
+                <li><a href="#">注册/登录</a></li>
+                @endauth
+
+                <li>
+                    <x-language-switcher />
+                </li>
+            </ul>
+
+            <button class="bc-hamburger" id="bcHamburger">
+                <i class="ti ti-menu-2"></i>
+            </button>
+
+        </div>
+    </div>
+</div>
+
+
+<div class="bc-mobile-overlay" id="bcOverlay"></div>
+
+<div class="bc-mobile-drawer" id="bcDrawer">
+    <div class="bc-mobile-drawer-header">
+        <span>导航</span>
+
+        <button class="bc-mobile-drawer-close" id="bcDrawerClose">
+            <i class="ti ti-x"></i>
+        </button>
+    </div>
+
+    <ul class="bc-mobile-nav">
+        <li><a href="{{ route('library.home') }}">首页</a></li>
+        <li><a href="{{ route('library.wiki.index') }}">百科</a></li>
+        <li><a href="{{ route('library.anthology.index') }}">文集</a></li>
+        <li><a href="{{ route('library.download') }}">下载</a></li>
+
+        @auth
+        <li><a href="#">我的账户</a></li>
+        @else
+        <li><a href="#">注册/登录</a></li>
+        @endauth
+
+        <li style="padding:1rem 1.25rem;">
+            <x-language-switcher />
+        </li>
+    </ul>
+</div>

+ 20 - 0
api-v12/resources/views/components/term-drawer.blade.php

@@ -0,0 +1,20 @@
+<div class="offcanvas offcanvas-bottom h-auto" tabindex="-1" id="termDrawer">
+
+    <div class="offcanvas-header">
+
+        <h5 class="offcanvas-title" id="termDrawerTitle">
+            术语解释
+        </h5>
+
+        <button
+            type="button"
+            class="btn-close"
+            data-bs-dismiss="offcanvas"></button>
+
+    </div>
+
+    <div class="offcanvas-body" id="termDrawerBody">
+        Loading...
+    </div>
+
+</div>