diff --git a/doc/index.php b/doc/index.php
new file mode 100644
index 0000000..b1fe8e5
--- /dev/null
+++ b/doc/index.php
@@ -0,0 +1,121 @@
+ 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 = '
';
+ foreach ($items as $item) {
+ if ($item['type'] === 'dir') {
+ $html .= '- ' . htmlspecialchars($item['name']) . '';
+ $html .= renderTree($item['children'], $currentFile);
+ $html .= '
';
+ } else {
+ $active = $currentFile === 'md/' . $item['path'] ? 'active' : '';
+ $html .= '- ' . htmlspecialchars($item['name']) . '
';
+ }
+ }
+ $html .= '
';
+ return $html;
+}
+?>
+
+
+
+
+
+ - Parlz Domains Docs
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/script.js b/doc/script.js
new file mode 100644
index 0000000..dda5788
--- /dev/null
+++ b/doc/script.js
@@ -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(' 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; }
+}
\ No newline at end of file