优化知识库展示

列表页改进:
- 显示元数据标题而非文件名
- 显示作者、发布时间、平台
- 显示正文概述前两行
- 根据平台显示图标

文章页改进:
- 过滤 YAML front matter
- 只显示正文内容
This commit is contained in:
2026-02-15 18:56:50 +08:00
parent cb59dba8e6
commit df5373adbc
3 changed files with 160 additions and 54 deletions
+100 -34
View File
@@ -9,6 +9,66 @@ $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 = [];
@@ -24,10 +84,8 @@ function scanDirectory($dir, $baseDir, $search) {
$relativePath = str_replace($baseDir . '/', '', $fullPath);
if (is_dir($fullPath)) {
// 递归扫描子目录
$docs = array_merge($docs, scanDirectory($fullPath, $baseDir, $search));
} elseif (is_file($fullPath)) {
// 只处理 .md 和 .txt 文件
$ext = strtolower(pathinfo($item, PATHINFO_EXTENSION));
if (!in_array($ext, ['md', 'txt', 'markdown'])) continue;
@@ -36,21 +94,26 @@ function scanDirectory($dir, $baseDir, $search) {
// 搜索过滤
if ($search) {
$searchLower = mb_strtolower($search);
$titleLower = mb_strtolower($item);
$contentLower = mb_strtolower($content);
if (strpos($titleLower, $searchLower) === false &&
strpos($contentLower, $searchLower) === false) {
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),
'preview' => mb_substr(strip_tags($content), 0, 200)
'title' => $meta['title'],
'author' => $meta['author'],
'date' => $meta['date'],
'platform' => $meta['platform'],
'summary' => $meta['summary']
];
}
}
@@ -59,21 +122,32 @@ function scanDirectory($dir, $baseDir, $search) {
$documents = scanDirectory($docDir, $docDir, $search);
// 按文件夹分组,然后按修改时间排序
// 按日期排序(新文件在前)
usort($documents, function($a, $b) {
// 先按文件夹排序
if ($a['folder'] !== $b['folder']) {
return strcmp($a['folder'], $b['folder']);
// 优先按日期排序
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-width, initial-scale=1.0">
<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>
@@ -115,34 +189,26 @@ usort($documents, function($a, $b) {
<?php endif; ?>
</div>
<?php else: ?>
<?php
$currentFolder = '';
foreach ($documents as $doc):
// 显示文件夹分隔
if ($doc['folder'] !== $currentFolder):
$currentFolder = $doc['folder'];
if ($currentFolder):
?>
<div class="folder-separator">
📁 <?php echo htmlspecialchars($currentFolder); ?>
</div>
<?php
endif;
endif;
?>
<?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">📄</div>
<div class="doc-icon"><?php echo getPlatformIcon($doc['platform']); ?></div>
<div class="doc-info">
<div class="doc-name"><?php echo htmlspecialchars($doc['name']); ?></div>
<div class="doc-title"><?php echo htmlspecialchars($doc['title']); ?></div>
<div class="doc-meta">
<?php echo round($doc['size'] / 1024, 1); ?> KB ·
<?php echo date('Y-m-d H:i', $doc['mtime']); ?>
<?php if ($doc['folder']): ?>
· 📁 <?php echo htmlspecialchars($doc['folder']); ?>
<?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>
<div class="doc-preview"><?php echo htmlspecialchars($doc['preview']); ?>...</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; ?>