上传文件至「doc」
这个提交包含在:
+121
@@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
$baseDir = __DIR__ . '/md';
|
||||||
|
$fileParam = isset($_GET['file']) ? trim($_GET['file']) : '';
|
||||||
|
$isAjax = isset($_GET['_ajax']);
|
||||||
|
if (empty($fileParam)) {
|
||||||
|
$files = glob($baseDir . '/*.md');
|
||||||
|
if ($files) {
|
||||||
|
usort($files, function($a, $b) {
|
||||||
|
return filemtime($b) - filemtime($a);
|
||||||
|
});
|
||||||
|
$fileParam = 'md/' . basename($files[0]);
|
||||||
|
} else {
|
||||||
|
$fileParam = 'md/index.md';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$fileParam = str_replace(['..', '/\\', "\0", '\\'], '', $fileParam);
|
||||||
|
if (!preg_match('/^md\/[a-zA-Z0-9_\-\x{4e00}-\x{9fff}]+(\/[a-zA-Z0-9_\-\x{4e00}-\x{9fff}]+)*\.md$/u', $fileParam)) {
|
||||||
|
if (preg_match('/^[a-zA-Z0-9_\-\x{4e00}-\x{9fff}]+(\/[a-zA-Z0-9_\-\x{4e00}-\x{9fff}]+)*\.md$/u', $fileParam)) {
|
||||||
|
$fileParam = '/doc/md/' . $fileParam;
|
||||||
|
} else {
|
||||||
|
$fileParam = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$mdFile = __DIR__ . '/' . $fileParam;
|
||||||
|
$content = '';
|
||||||
|
$title = 'Docs';
|
||||||
|
$currentFile = $fileParam;
|
||||||
|
$pathParts = explode('/', $fileParam);
|
||||||
|
$pageName = basename($fileParam, '.md');
|
||||||
|
$folderName = (count($pathParts) > 2) ? $pathParts[1] : '';
|
||||||
|
$title = ucfirst($pageName);
|
||||||
|
if (!empty($fileParam) && file_exists($mdFile) && is_file($mdFile)) {
|
||||||
|
$rawContent = file_get_contents($mdFile);
|
||||||
|
} else {
|
||||||
|
$rawContent = '';
|
||||||
|
$title = '未找到';
|
||||||
|
}
|
||||||
|
if ($isAjax) {
|
||||||
|
echo $rawContent;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
function getDirStructure($dir, $base = '') {
|
||||||
|
$items = [];
|
||||||
|
$entries = scandir($dir);
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
if ($entry === '.' || $entry === '..') continue;
|
||||||
|
$path = $dir . '/' . $entry;
|
||||||
|
$rel = $base ? $base . '/' . $entry : $entry;
|
||||||
|
if (is_dir($path)) {
|
||||||
|
$items[] = ['type' => 'dir', 'name' => $entry, 'path' => $rel, 'children' => getDirStructure($path, $rel)];
|
||||||
|
} elseif (pathinfo($path, PATHINFO_EXTENSION) === 'md') {
|
||||||
|
$items[] = ['type' => 'file', 'name' => $entry, 'path' => $rel];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
$tree = getDirStructure($baseDir);
|
||||||
|
function renderTree($items, $currentFile) {
|
||||||
|
$html = '<ul>';
|
||||||
|
foreach ($items as $item) {
|
||||||
|
if ($item['type'] === 'dir') {
|
||||||
|
$html .= '<li class="folder"><span class="folder-toggle"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg> ' . htmlspecialchars($item['name']) . '</span>';
|
||||||
|
$html .= renderTree($item['children'], $currentFile);
|
||||||
|
$html .= '</li>';
|
||||||
|
} else {
|
||||||
|
$active = $currentFile === 'md/' . $item['path'] ? 'active' : '';
|
||||||
|
$html .= '<li class="file ' . $active . '"><a href="/doc/?file=md/' . $item['path'] . '"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg> ' . htmlspecialchars($item['name']) . '</a></li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$html .= '</ul>';
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN" data-theme="light">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php echo htmlspecialchars($title); ?> - Parlz Domains Docs</title>
|
||||||
|
<link rel="stylesheet" href="/doc/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layout">
|
||||||
|
<aside class="sidebar">
|
||||||
|
<div class="sidebar-header">
|
||||||
|
<h1>文档列表</h1>
|
||||||
|
<button class="theme-toggle" id="themeToggle">
|
||||||
|
<svg class="sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
|
||||||
|
<svg class="moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" id="searchInput" placeholder="搜索任何文档...">
|
||||||
|
</div>
|
||||||
|
<nav class="nav-tree" id="navTree">
|
||||||
|
<?php echo renderTree($tree, $currentFile); ?>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
<main class="content">
|
||||||
|
<div class="mobile-header">
|
||||||
|
<button class="menu-toggle" id="menuToggle">☰</button>
|
||||||
|
<span class="mobile-title">Parlz Domains Docs</span>
|
||||||
|
<button class="theme-toggle" id="mobileThemeToggle">
|
||||||
|
<svg class="sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
|
||||||
|
<svg class="moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="markdown-body" id="markdownBody">
|
||||||
|
<?php if ($rawContent): ?>
|
||||||
|
<?php echo $rawContent; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<p>暂无文档</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<div class="overlay" id="overlay"></div>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
<script src="/doc/script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+198
@@ -0,0 +1,198 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const markdownBody = document.getElementById('markdownBody');
|
||||||
|
const rawContent = markdownBody.innerHTML;
|
||||||
|
markdownBody.innerHTML = marked.parse(rawContent);
|
||||||
|
|
||||||
|
const themeToggle = document.getElementById('themeToggle');
|
||||||
|
const mobileThemeToggle = document.getElementById('mobileThemeToggle');
|
||||||
|
const html = document.documentElement;
|
||||||
|
|
||||||
|
function setTheme(theme) {
|
||||||
|
html.setAttribute('data-theme', theme);
|
||||||
|
localStorage.setItem('theme', theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleTheme() {
|
||||||
|
const current = html.getAttribute('data-theme');
|
||||||
|
setTheme(current === 'dark' ? 'light' : 'dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
const saved = localStorage.getItem('theme');
|
||||||
|
if (saved) {
|
||||||
|
setTheme(saved);
|
||||||
|
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
|
setTheme('dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
themeToggle.addEventListener('click', toggleTheme);
|
||||||
|
if (mobileThemeToggle) mobileThemeToggle.addEventListener('click', toggleTheme);
|
||||||
|
|
||||||
|
const menuToggle = document.getElementById('menuToggle');
|
||||||
|
const sidebar = document.querySelector('.sidebar');
|
||||||
|
const overlay = document.getElementById('overlay');
|
||||||
|
|
||||||
|
if (menuToggle) {
|
||||||
|
menuToggle.addEventListener('click', function() {
|
||||||
|
sidebar.classList.toggle('open');
|
||||||
|
overlay.classList.toggle('show');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overlay) {
|
||||||
|
overlay.addEventListener('click', function() {
|
||||||
|
sidebar.classList.remove('open');
|
||||||
|
overlay.classList.remove('show');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const folders = document.querySelectorAll('.folder-toggle');
|
||||||
|
folders.forEach(function(folder) {
|
||||||
|
folder.addEventListener('click', function() {
|
||||||
|
const li = this.parentElement;
|
||||||
|
li.classList.toggle('open');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchInput = document.getElementById('searchInput');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.addEventListener('input', function() {
|
||||||
|
const query = this.value.toLowerCase().trim();
|
||||||
|
const files = document.querySelectorAll('.nav-tree .file');
|
||||||
|
const dirs = document.querySelectorAll('.nav-tree .folder');
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
files.forEach(f => f.classList.remove('hidden'));
|
||||||
|
dirs.forEach(d => d.classList.remove('hidden'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
files.forEach(function(file) {
|
||||||
|
const text = file.textContent.toLowerCase();
|
||||||
|
if (text.includes(query)) {
|
||||||
|
file.classList.remove('hidden');
|
||||||
|
let parent = file.parentElement;
|
||||||
|
while (parent) {
|
||||||
|
if (parent.classList && parent.classList.contains('folder')) {
|
||||||
|
parent.classList.remove('hidden');
|
||||||
|
parent.classList.add('open');
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file.classList.add('hidden');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dirs.forEach(function(dir) {
|
||||||
|
const visibleFiles = dir.querySelectorAll('.file:not(.hidden)');
|
||||||
|
if (visibleFiles.length === 0) {
|
||||||
|
const folderText = dir.querySelector('.folder-toggle').textContent.toLowerCase();
|
||||||
|
if (!folderText.includes(query)) {
|
||||||
|
dir.classList.add('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentFile = document.querySelector('.nav-tree .file.active');
|
||||||
|
if (currentFile) {
|
||||||
|
let parent = currentFile.parentElement;
|
||||||
|
while (parent) {
|
||||||
|
if (parent.classList && parent.classList.contains('folder')) {
|
||||||
|
parent.classList.add('open');
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
currentFile.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const navTree = document.getElementById('navTree');
|
||||||
|
if (navTree) {
|
||||||
|
navTree.addEventListener('click', function(e) {
|
||||||
|
const link = e.target.closest('a');
|
||||||
|
if (!link) return;
|
||||||
|
const href = link.getAttribute('href');
|
||||||
|
if (!href || href.startsWith('http') || href.startsWith('#') || href.startsWith('javascript')) return;
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const sidebarEl = document.querySelector('.sidebar');
|
||||||
|
const overlayEl = document.getElementById('overlay');
|
||||||
|
if (sidebarEl.classList.contains('open')) {
|
||||||
|
sidebarEl.classList.remove('open');
|
||||||
|
overlayEl.classList.remove('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
history.pushState(null, '', href);
|
||||||
|
loadDoc(href);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 使用 XMLHttpRequest 替代 fetch =====
|
||||||
|
function loadDoc(href) {
|
||||||
|
var url = '/doc/index.php' + href + '&_ajax=1';
|
||||||
|
markdownBody.style.opacity = '0.5';
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.timeout = 30000; // 30秒超时
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
markdownBody.style.opacity = '1';
|
||||||
|
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
var data = xhr.responseText;
|
||||||
|
// 检查是否返回了 HTML(说明请求失败)
|
||||||
|
if (data.trim().startsWith('<!DOCTYPE') || data.trim().startsWith('<html')) {
|
||||||
|
// 降级:直接跳转
|
||||||
|
window.location.href = href;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
markdownBody.innerHTML = marked.parse(data);
|
||||||
|
var titleEl = markdownBody.querySelector('h1');
|
||||||
|
var newTitle = titleEl ? titleEl.textContent + ' - Docs' : 'Docs - Docs';
|
||||||
|
document.title = newTitle;
|
||||||
|
updateActiveLink(href);
|
||||||
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
|
} else {
|
||||||
|
// 请求失败,降级跳转
|
||||||
|
console.error('加载失败,状态码: ' + xhr.status);
|
||||||
|
window.location.href = href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function() {
|
||||||
|
markdownBody.style.opacity = '1';
|
||||||
|
console.error('网络错误');
|
||||||
|
window.location.href = href;
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.ontimeout = function() {
|
||||||
|
markdownBody.style.opacity = '1';
|
||||||
|
console.error('请求超时');
|
||||||
|
window.location.href = href;
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateActiveLink(href) {
|
||||||
|
document.querySelectorAll('.nav-tree .file').forEach(function(f) {
|
||||||
|
f.classList.remove('active');
|
||||||
|
var a = f.querySelector('a');
|
||||||
|
if (a && a.getAttribute('href') === href) {
|
||||||
|
f.classList.add('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('popstate', function() {
|
||||||
|
var params = new URLSearchParams(window.location.search);
|
||||||
|
var f = params.get('file');
|
||||||
|
if (f) {
|
||||||
|
loadDoc('?file=' + f);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
+396
@@ -0,0 +1,396 @@
|
|||||||
|
@import url("https://cdn.jsdmirror.com/gh/willow-god/Sharding-fonts/Yozai-Medium/result.min.css");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--bg-primary: #ffffff;
|
||||||
|
--bg-secondary: #f8fafc;
|
||||||
|
--bg-sidebar: #f1f5f9;
|
||||||
|
--text-primary: #1e293b;
|
||||||
|
--text-secondary: #64748b;
|
||||||
|
--text-muted: #94a3b8;
|
||||||
|
--border-color: #e2e8f0;
|
||||||
|
--accent-color: #3b82f6;
|
||||||
|
--accent-hover: #2563eb;
|
||||||
|
--code-bg: #f1f5f9;
|
||||||
|
--code-text: #334155;
|
||||||
|
--shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||||
|
--shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1);
|
||||||
|
--radius: 8px;
|
||||||
|
--radius-lg: 12px;
|
||||||
|
--font-sans: 'Yozai Medium';
|
||||||
|
--font-mono: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--bg-primary: #0f172a;
|
||||||
|
--bg-secondary: #1e293b;
|
||||||
|
--bg-sidebar: #1e293b;
|
||||||
|
--text-primary: #f1f5f9;
|
||||||
|
--text-secondary: #94a3b8;
|
||||||
|
--text-muted: #64748b;
|
||||||
|
--border-color: #334155;
|
||||||
|
--accent-color: #60a5fa;
|
||||||
|
--accent-hover: #3b82f6;
|
||||||
|
--code-bg: #1e293b;
|
||||||
|
--code-text: #e2e8f0;
|
||||||
|
--shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||||
|
--shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
line-height: 1.6;
|
||||||
|
transition: background 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 280px;
|
||||||
|
background: var(--bg-sidebar);
|
||||||
|
border-right: 1px solid var(--border-color);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: fixed;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
transition: transform 0.3s, background 0.3s;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-header {
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-header h1 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
transition: all 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle:hover {
|
||||||
|
background: var(--accent-color);
|
||||||
|
color: #fff;
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-toggle .moon { display: none; }
|
||||||
|
[data-theme="dark"] .theme-toggle .sun { display: none; }
|
||||||
|
[data-theme="dark"] .theme-toggle .moon { display: block; }
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
padding: 12px 20px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box input:focus {
|
||||||
|
border-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box input::placeholder {
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree {
|
||||||
|
padding: 12px 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .folder-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: color 0.2s;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .folder-toggle:hover {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .folder-toggle svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .folder > ul {
|
||||||
|
display: none;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .folder.open > ul {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .file a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 20px 6px 32px;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
border-left: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .file a:hover {
|
||||||
|
color: var(--accent-color);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .file.active a {
|
||||||
|
color: var(--accent-color);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-left-color: var(--accent-color);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tree .file.hidden,
|
||||||
|
.nav-tree .folder.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-left: 280px;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-header {
|
||||||
|
display: none;
|
||||||
|
padding: 12px 20px;
|
||||||
|
background: var(--bg-sidebar);
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-toggle {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1rem;
|
||||||
|
flex: 1;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body {
|
||||||
|
padding: 40px 48px;
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h1,
|
||||||
|
.markdown-body h2,
|
||||||
|
.markdown-body h3,
|
||||||
|
.markdown-body h4,
|
||||||
|
.markdown-body h5,
|
||||||
|
.markdown-body h6 {
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.3;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body h1 { font-size: 2rem; border-bottom: 1px solid var(--border-color); padding-bottom: 0.5rem; }
|
||||||
|
.markdown-body h2 { font-size: 1.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 0.4rem; }
|
||||||
|
.markdown-body h3 { font-size: 1.25rem; }
|
||||||
|
.markdown-body h4 { font-size: 1.1rem; }
|
||||||
|
|
||||||
|
.markdown-body p {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body a {
|
||||||
|
color: var(--accent-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body ul,
|
||||||
|
.markdown-body ol {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body li {
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body code {
|
||||||
|
background: var(--code-bg);
|
||||||
|
color: var(--code-text);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body pre {
|
||||||
|
background: var(--code-bg);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 1rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body pre code {
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body blockquote {
|
||||||
|
border-left: 3px solid var(--accent-color);
|
||||||
|
padding-left: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body th,
|
||||||
|
.markdown-body td {
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body th {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body tr:nth-child(even) {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body img[src*=".svg"] {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.sidebar {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar.open {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.markdown-body h1 { font-size: 1.5rem; }
|
||||||
|
.markdown-body h2 { font-size: 1.25rem; }
|
||||||
|
.markdown-body { padding: 16px; }
|
||||||
|
}
|
||||||
在新工单中引用
屏蔽一个用户