This repository has been archived on 2026-03-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
kb-web/dashboard.php
T
starmen1265 df5373adbc 优化知识库展示
列表页改进:
- 显示元数据标题而非文件名
- 显示作者、发布时间、平台
- 显示正文概述前两行
- 根据平台显示图标

文章页改进:
- 过滤 YAML front matter
- 只显示正文内容
2026-02-15 18:56:50 +08:00

220 lines
7.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once 'config.php';
checkLogin();
$user = getCurrentUser();
$username = $user['username'];
$docDir = getUserDocDir($username);
// 搜索关键词
$search = trim($_GET['q'] ?? '');
// 解析 Markdown 文件的 YAML front matter
function parseMarkdownWithMeta($filePath) {
$content = file_get_contents($filePath);
$meta = [
'title' => basename($filePath),
'author' => '',
'date' => '',
'platform' => '',
'url' => '',
'summary' => ''
];
// 解析 YAML front matter
if (preg_match('/^---\s*\n(.*?)\n---\s*\n(.*)$/s', $content, $matches)) {
$yaml = $matches[1];
$body = $matches[2];
// 解析 YAML 字段
if (preg_match('/^title:\s*["\']?(.+?)["\']?\s*$/m', $yaml, $m)) {
$meta['title'] = trim($m[1], '"\'');
}
if (preg_match('/^author:\s*(.+?)\s*$/m', $yaml, $m)) {
$meta['author'] = trim($m[1]);
}
if (preg_match('/^date:\s*(.+?)\s*$/m', $yaml, $m)) {
$meta['date'] = trim($m[1]);
}
if (preg_match('/^platform:\s*(.+?)\s*$/m', $yaml, $m)) {
$meta['platform'] = trim($m[1]);
}
if (preg_match('/^url:\s*(.+?)\s*$/m', $yaml, $m)) {
$meta['url'] = trim($m[1]);
}
// 提取正文概述(前两行非空内容)
$lines = preg_split('/\r?\n/', trim($body));
$summaryLines = [];
foreach ($lines as $line) {
$line = trim($line);
if (empty($line) || strpos($line, '##') === 0) continue;
$summaryLines[] = $line;
if (count($summaryLines) >= 2) break;
}
$meta['summary'] = implode(' ', $summaryLines);
} else {
// 没有 front matter,从正文提取
$lines = preg_split('/\r?\n/', trim($content));
$summaryLines = [];
foreach ($lines as $line) {
$line = trim($line);
if (empty($line) || strpos($line, '#') === 0) continue;
$summaryLines[] = $line;
if (count($summaryLines) >= 2) break;
}
$meta['summary'] = implode(' ', $summaryLines);
}
return $meta;
}
// 递归获取文档列表
$documents = [];
function scanDirectory($dir, $baseDir, $search) {
$docs = [];
if (!is_dir($dir)) return $docs;
$items = scandir($dir);
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$fullPath = $dir . '/' . $item;
$relativePath = str_replace($baseDir . '/', '', $fullPath);
if (is_dir($fullPath)) {
$docs = array_merge($docs, scanDirectory($fullPath, $baseDir, $search));
} elseif (is_file($fullPath)) {
$ext = strtolower(pathinfo($item, PATHINFO_EXTENSION));
if (!in_array($ext, ['md', 'txt', 'markdown'])) continue;
$content = file_get_contents($fullPath);
// 搜索过滤
if ($search) {
$searchLower = mb_strtolower($search);
$contentLower = mb_strtolower($content);
if (strpos($contentLower, $searchLower) === false) {
continue;
}
}
// 解析元数据
$meta = parseMarkdownWithMeta($fullPath);
$docs[] = [
'name' => $item,
'path' => $relativePath,
'folder' => dirname($relativePath) === '.' ? '' : dirname($relativePath),
'size' => filesize($fullPath),
'mtime' => filemtime($fullPath),
'title' => $meta['title'],
'author' => $meta['author'],
'date' => $meta['date'],
'platform' => $meta['platform'],
'summary' => $meta['summary']
];
}
}
return $docs;
}
$documents = scanDirectory($docDir, $docDir, $search);
// 按日期排序(新文件在前)
usort($documents, function($a, $b) {
// 优先按日期排序
if ($a['date'] && $b['date']) {
return strcmp($b['date'], $a['date']);
}
// 其次按修改时间
return $b['mtime'] - $a['mtime'];
});
// 平台图标映射
function getPlatformIcon($platform) {
$icons = [
'bilibili' => '📺',
'youtube' => '▶️',
'zhihu' => '💡',
'wechat' => '💬',
];
return $icons[$platform] ?? '📄';
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device=device-width, initial-scale=1.0">
<title>知识库 - <?php echo htmlspecialchars($username); ?></title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="dashboard">
<header class="header">
<h1>📚 我的知识库</h1>
<div class="user-info">
<span><?php echo htmlspecialchars($username); ?></span>
<a href="logout.php" class="btn-logout">退出</a>
</div>
</header>
<div class="search-bar">
<form method="GET" action="">
<input type="text" name="q" placeholder="搜索文档..."
value="<?php echo htmlspecialchars($search); ?>">
<button type="submit">搜索</button>
<?php if ($search): ?>
<a href="dashboard.php" class="btn-clear">清除</a>
<?php endif; ?>
</form>
</div>
<div class="stats">
共 <?php echo count($documents); ?> 个文档
<?php if ($search): ?>
<span class="search-hint">(搜索: "<?php echo htmlspecialchars($search); ?>")</span>
<?php endif; ?>
</div>
<div class="document-list">
<?php if (empty($documents)): ?>
<div class="empty">
<?php if ($search): ?>
没有找到匹配的文档
<?php else: ?>
暂无文档
<?php endif; ?>
</div>
<?php else: ?>
<?php foreach ($documents as $doc): ?>
<a href="view.php?file=<?php echo urlencode($doc['path']); ?><?php echo $search ? '&q=' . urlencode($search) : ''; ?>"
class="document-card">
<div class="doc-icon"><?php echo getPlatformIcon($doc['platform']); ?></div>
<div class="doc-info">
<div class="doc-title"><?php echo htmlspecialchars($doc['title']); ?></div>
<div class="doc-meta">
<?php if ($doc['author']): ?>
<span class="meta-author">👤 <?php echo htmlspecialchars($doc['author']); ?></span>
<?php endif; ?>
<?php if ($doc['date']): ?>
<span class="meta-date">📅 <?php echo htmlspecialchars($doc['date']); ?></span>
<?php endif; ?>
<?php if ($doc['platform']): ?>
<span class="meta-platform">🏷️ <?php echo htmlspecialchars($doc['platform']); ?></span>
<?php endif; ?>
</div>
<?php if ($doc['summary']): ?>
<div class="doc-summary"><?php echo htmlspecialchars(mb_substr($doc['summary'], 0, 150)); ?><?php echo mb_strlen($doc['summary']) > 150 ? '...' : ''; ?></div>
<?php endif; ?>
</div>
</a>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</body>
</html>